solana-agent 17.0.1__py3-none-any.whl → 17.0.3__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.
@@ -19,7 +19,7 @@ class OpenAIAdapter(LLMProvider):
19
19
  def __init__(self, api_key: str):
20
20
  self.client = OpenAI(api_key=api_key)
21
21
  self.parse_model = "gpt-4o-mini"
22
- self.search_model = "gpt-4o-mini-search-preview"
22
+ self.text_model = "gpt-4o-mini"
23
23
  self.transcription_model = "gpt-4o-mini-transcribe"
24
24
  self.tts_model = "tts-1"
25
25
 
@@ -106,7 +106,7 @@ class OpenAIAdapter(LLMProvider):
106
106
  prompt: str,
107
107
  system_prompt: str = "",
108
108
  ) -> AsyncGenerator[str, None]: # pragma: no cover
109
- """Generate text from OpenAI models with web search capability."""
109
+ """Generate text from OpenAI models."""
110
110
  messages = []
111
111
 
112
112
  if system_prompt:
@@ -118,7 +118,7 @@ class OpenAIAdapter(LLMProvider):
118
118
  request_params = {
119
119
  "messages": messages,
120
120
  "stream": True,
121
- "model": self.search_model,
121
+ "model": self.text_model,
122
122
  }
123
123
  try:
124
124
  response = self.client.chat.completions.create(**request_params)
@@ -39,6 +39,7 @@ class AgentService(AgentServiceInterface):
39
39
  self.agent_repository = agent_repository
40
40
  self.organization_mission = organization_mission
41
41
  self.config = config or {}
42
+ self.last_text_response = ""
42
43
 
43
44
  # Initialize tool registry with concrete implementation
44
45
  if tool_registry:
@@ -247,7 +248,10 @@ class AgentService(AgentServiceInterface):
247
248
  if memory_context:
248
249
  system_prompt += f"\n\nMemory Context: {memory_context}"
249
250
 
250
- # Buffer for collecting text when generating audio
251
+ # Keep track of the complete text response
252
+ complete_text_response = ""
253
+ json_buffer = ""
254
+ is_json = False
251
255
  text_buffer = ""
252
256
 
253
257
  # Generate and stream response
@@ -255,40 +259,107 @@ class AgentService(AgentServiceInterface):
255
259
  prompt=query_text,
256
260
  system_prompt=system_prompt,
257
261
  ):
258
- if chunk.strip().startswith("{"):
259
- # Handle tool calls
260
- result = await self._handle_tool_call(
261
- agent_name, chunk,
262
- )
263
- if output_format == "audio":
264
- async for audio_chunk in self.llm_provider.tts(result, instructions=audio_instructions, response_format=audio_output_format, voice=audio_voice):
265
- yield audio_chunk
266
- else:
267
- yield result
262
+ # Check for JSON start
263
+ if chunk.strip().startswith("{") and not is_json:
264
+ is_json = True
265
+ json_buffer = chunk
266
+ continue
267
+
268
+ # Collect JSON or handle normal text
269
+ if is_json:
270
+ json_buffer += chunk
271
+ try:
272
+ # Try to parse complete JSON
273
+ data = json.loads(json_buffer)
274
+
275
+ # Valid JSON found, handle it
276
+ if "tool_call" in data:
277
+ # Process tool call with existing method
278
+ response_text = await self._handle_tool_call(
279
+ agent_name=agent_name,
280
+ json_chunk=json_buffer
281
+ )
282
+
283
+ # Add to complete text response
284
+ complete_text_response += response_text
285
+
286
+ # Output response based on format
287
+ if output_format == "audio":
288
+ async for audio_chunk in self.llm_provider.tts(
289
+ text=response_text,
290
+ voice=audio_voice,
291
+ response_format=audio_output_format
292
+ ):
293
+ yield audio_chunk
294
+ else:
295
+ yield response_text
296
+ else:
297
+ # For non-tool JSON, still capture the text
298
+ complete_text_response += json_buffer
299
+
300
+ if output_format == "audio":
301
+ async for audio_chunk in self.llm_provider.tts(
302
+ text=json_buffer,
303
+ voice=audio_voice,
304
+ response_format=audio_output_format
305
+ ):
306
+ yield audio_chunk
307
+ else:
308
+ yield json_buffer
309
+
310
+ # Reset JSON handling
311
+ is_json = False
312
+ json_buffer = ""
313
+
314
+ except json.JSONDecodeError:
315
+ pass
268
316
  else:
317
+ # For regular text, always add to the complete response
318
+ complete_text_response += chunk
319
+
320
+ # Handle audio buffering or direct text output
269
321
  if output_format == "audio":
270
- # Buffer text until we have a complete sentence
271
322
  text_buffer += chunk
272
323
  if any(punct in chunk for punct in ".!?"):
273
324
  async for audio_chunk in self.llm_provider.tts(
274
- text_buffer, instructions=audio_instructions, response_format=audio_output_format, voice=audio_voice
325
+ text=text_buffer,
326
+ voice=audio_voice,
327
+ response_format=audio_output_format
275
328
  ):
276
329
  yield audio_chunk
277
330
  text_buffer = ""
278
331
  else:
279
332
  yield chunk
280
333
 
281
- # Handle any remaining text in buffer
282
- if output_format == "audio" and text_buffer:
283
- async for audio_chunk in self.llm_provider.tts(
284
- text_buffer, instructions=audio_instructions, response_format=audio_output_format, voice=audio_voice
285
- ):
286
- yield audio_chunk
334
+ # Handle any remaining text or incomplete JSON
335
+ remaining_text = ""
336
+ if text_buffer:
337
+ remaining_text += text_buffer
338
+ if is_json and json_buffer:
339
+ remaining_text += json_buffer
340
+
341
+ if remaining_text:
342
+ # Add remaining text to complete response
343
+ complete_text_response += remaining_text
344
+
345
+ if output_format == "audio":
346
+ async for audio_chunk in self.llm_provider.tts(
347
+ text=remaining_text,
348
+ voice=audio_voice,
349
+ response_format=audio_output_format
350
+ ):
351
+ yield audio_chunk
352
+ else:
353
+ yield remaining_text
354
+
355
+ # Store the complete text response for the caller to access
356
+ # This needs to be done in the query service using the self.last_text_response
357
+ self.last_text_response = complete_text_response
287
358
 
288
359
  except Exception as e:
289
360
  error_msg = f"I apologize, but I encountered an error: {str(e)}"
290
361
  if output_format == "audio":
291
- async for chunk in self.llm_provider.tts(error_msg, instructions=audio_instructions, response_format=audio_output_format, voice=audio_voice):
362
+ async for chunk in self.llm_provider.tts(error_msg, voice=audio_voice, response_format=audio_output_format):
292
363
  yield chunk
293
364
  else:
294
365
  yield error_msg
@@ -52,11 +52,8 @@ class QueryService(QueryServiceInterface):
52
52
  Args:
53
53
  user_id: User ID
54
54
  query: Text query or audio bytes
55
- output_format: Response format ("text" or "audio")
56
- audio_voice: Voice to use for audio output
57
- audio_instructions: Optional instructions for audio synthesis
58
- audio_output_format: Audio output format
59
- audio_input_format: Audio input format
55
+ output_format: Response format ("text" or "audio")
56
+ voice: Voice to use for audio output
60
57
 
61
58
  Yields:
62
59
  Response chunks (text strings or audio bytes)
@@ -74,7 +71,11 @@ class QueryService(QueryServiceInterface):
74
71
  if user_text.strip().lower() in ["test", "hello", "hi", "hey", "ping"]:
75
72
  response = "Hello! How can I help you today?"
76
73
  if output_format == "audio":
77
- async for chunk in self.agent_service.llm_provider.tts(response, instructions=audio_instructions, response_format=audio_output_format, voice=audio_voice):
74
+ async for chunk in self.agent_service.llm_provider.tts(
75
+ text=response,
76
+ voice=audio_voice,
77
+ response_format=audio_output_format
78
+ ):
78
79
  yield chunk
79
80
  else:
80
81
  yield response
@@ -91,42 +92,47 @@ class QueryService(QueryServiceInterface):
91
92
 
92
93
  # Route query to appropriate agent
93
94
  agent_name = await self.routing_service.route_query(user_text)
95
+ print(f"DEBUG: Routed to agent: {agent_name}")
94
96
 
95
- # Generate response using agent service
96
- full_response = ""
97
- async for chunk in self.agent_service.generate_response(
98
- agent_name=agent_name,
99
- user_id=user_id,
100
- query=user_text,
101
- memory_context=memory_context,
102
- output_format=output_format,
103
- audio_voice=audio_voice,
104
- audio_output_format=audio_output_format,
105
- ):
106
- yield chunk
107
- if output_format == "text":
97
+ # For text output, we can directly collect and yield chunks
98
+ if output_format == "text":
99
+ full_response = ""
100
+ async for chunk in self.agent_service.generate_response(
101
+ agent_name=agent_name,
102
+ user_id=user_id,
103
+ query=user_text,
104
+ memory_context=memory_context,
105
+ output_format="text",
106
+ ):
107
+ yield chunk
108
108
  full_response += chunk
109
109
 
110
- # For audio responses, get transcription for storage
111
- if output_format == "audio":
112
- # Re-generate response in text format for storage
110
+ # For audio output, we'll yield audio chunks while collecting text separately
111
+ else:
113
112
  async for chunk in self.agent_service.generate_response(
114
113
  agent_name=agent_name,
115
114
  user_id=user_id,
116
115
  query=user_text,
117
116
  memory_context=memory_context,
118
- output_format="text"
117
+ output_format="audio",
118
+ audio_input_format=audio_input_format,
119
+ audio_output_format=audio_output_format,
120
+ audio_voice=audio_voice,
119
121
  ):
120
- full_response += chunk
122
+ yield chunk
121
123
 
122
- # Store conversation and extract insights
124
+ # Store conversation with the full text response
123
125
  if self.memory_provider:
124
- await self._store_conversation(user_id, user_text, full_response)
126
+ await self._store_conversation(user_id, user_text, self.agent_service.last_text_response)
125
127
 
126
128
  except Exception as e:
127
129
  error_msg = f"I apologize for the technical difficulty. {str(e)}"
128
130
  if output_format == "audio":
129
- async for chunk in self.agent_service.llm_provider.tts(error_msg, instructions=audio_instructions, response_format=audio_output_format, voice=audio_voice):
131
+ async for chunk in self.agent_service.llm_provider.tts(
132
+ text=error_msg,
133
+ voice=audio_voice,
134
+ response_format=audio_output_format
135
+ ):
130
136
  yield chunk
131
137
  else:
132
138
  yield error_msg
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: solana-agent
3
- Version: 17.0.1
3
+ Version: 17.0.3
4
4
  Summary: The Future of Work
5
5
  License: MIT
6
6
  Keywords: ai,openai,ai agents,agi
@@ -37,7 +37,6 @@ Description-Content-Type: text/markdown
37
37
  * Multi-modal input-output streaming with text or audio by AI Agents
38
38
  * Conversational memory per user shared by all AI Agents
39
39
  * Routing based on AI Agent specializations
40
- * Built-in Internet Search for all AI Agents
41
40
  * Organizational mission, values, goals, and guidance for all AI Agents
42
41
  * Robust AI Agent tool plugins based on standard python packages
43
42
 
@@ -110,7 +109,7 @@ async for response in solana_agent.process("user123", "What are the latest AI de
110
109
  ```
111
110
 
112
111
  ## Models Used
113
- * The model used for AI Agents is `gpt-4o-mini-search-preview`
112
+ * The model used for AI Agents is `gpt-4o-mini`
114
113
  * The model used for internal structured outputs is `gpt-4o-mini`
115
114
  * The model used for audio_transcription is `gpt-4o-mini-transcribe`
116
115
  * The model used for tts is `tts-1`
@@ -1,6 +1,6 @@
1
1
  solana_agent/__init__.py,sha256=ceYeUpjIitpln8YK1r0JVJU8mzG6cRPYu-HLny3d-Tw,887
2
2
  solana_agent/adapters/__init__.py,sha256=tiEEuuy0NF3ngc_tGEcRTt71zVI58v3dYY9RvMrF2Cg,204
3
- solana_agent/adapters/llm_adapter.py,sha256=s9eZkS1b-m7hK99hPLK421AFkud2jySFg4u4qNB9ayE,6080
3
+ solana_agent/adapters/llm_adapter.py,sha256=hi2JYj6CvhNLJxznIv_7Ef7Y0mk7aztHd_OMYe2scMQ,6034
4
4
  solana_agent/adapters/mongodb_adapter.py,sha256=qqEFbY_v1XGyFXBmwd5HSXSSHnA9wWo-Hm1vGEyIG0k,2718
5
5
  solana_agent/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  solana_agent/client/solana_agent.py,sha256=G0m6GD6N8J3tpjfLoKBMzIR3cZU9qs9cDBfY1mngvzI,4207
@@ -28,10 +28,10 @@ solana_agent/repositories/__init__.py,sha256=fP83w83CGzXLnSdq-C5wbw9EhWTYtqE2lQT
28
28
  solana_agent/repositories/agent.py,sha256=e1rnsQiigkKwJNLKro86a3b6TBiky3GMfmCRc5b_jPw,3187
29
29
  solana_agent/repositories/memory.py,sha256=GABGwaz00thjviHewLvb18NeKE8dkBROxy_stsiiWrE,4722
30
30
  solana_agent/services/__init__.py,sha256=ab_NXJmwYUCmCrCzuTlZ47bJZINW0Y0F5jfQ9OovidU,163
31
- solana_agent/services/agent.py,sha256=5BCzy8h37HAzvxiuOanu-RM_ARxwIdOUNie8xPLGDj0,14219
32
- solana_agent/services/query.py,sha256=N0RMcQm7o4B0MGrbFFrZ_Ar5z9r-UUDgn1xzgoxQtqg,10758
31
+ solana_agent/services/agent.py,sha256=j0aI_BGaY5Nhkb9ga0r4BqI3qMKu5TOc4QPQsU3NHyQ,17000
32
+ solana_agent/services/query.py,sha256=1BAb4UjpydwtJjut8oq724BJohe9ceMigMX-rkI5j7s,10820
33
33
  solana_agent/services/routing.py,sha256=TPJ2Pas4acE93QzMEV6ZP670OtTNrVEPa76fz6urEV4,4996
34
- solana_agent-17.0.1.dist-info/LICENSE,sha256=BnSRc-NSFuyF2s496l_4EyrwAP6YimvxWcjPiJ0J7g4,1057
35
- solana_agent-17.0.1.dist-info/METADATA,sha256=-KgZSOm4jpeQsuy8tCQs6lGFqfwJjTsqf3tZRLs_OwI,4948
36
- solana_agent-17.0.1.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
37
- solana_agent-17.0.1.dist-info/RECORD,,
34
+ solana_agent-17.0.3.dist-info/LICENSE,sha256=BnSRc-NSFuyF2s496l_4EyrwAP6YimvxWcjPiJ0J7g4,1057
35
+ solana_agent-17.0.3.dist-info/METADATA,sha256=kioM7hvaI97S8skANaI4oAcS2gnKgGMvI2jKTTHf5vg,4888
36
+ solana_agent-17.0.3.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
37
+ solana_agent-17.0.3.dist-info/RECORD,,