solana-agent 22.0.1__py3-none-any.whl → 22.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.
@@ -22,12 +22,12 @@ class OpenAIAdapter(LLMProvider):
22
22
  self.text_model = "gpt-4o-mini"
23
23
  self.internet_search_model = "gpt-4o-mini-search-preview"
24
24
  self.transcription_model = "gpt-4o-mini-transcribe"
25
- self.tts_model = "tts-1"
25
+ self.tts_model = "gpt-4o-mini-tts"
26
26
 
27
27
  async def tts(
28
28
  self,
29
29
  text: str,
30
- instructions: str = "",
30
+ instructions: str = "You speak in a friendly and helpful manner.",
31
31
  voice: Literal["alloy", "ash", "ballad", "coral", "echo",
32
32
  "fable", "onyx", "nova", "sage", "shimmer"] = "nova",
33
33
  response_format: Literal['mp3', 'opus',
@@ -45,16 +45,16 @@ class OpenAIAdapter(LLMProvider):
45
45
  Audio bytes as they become available
46
46
  """
47
47
  try:
48
- stream = self.client.audio.speech.create(
48
+ with self.client.audio.speech.with_streaming_response.create(
49
49
  model=self.tts_model,
50
50
  voice=voice,
51
+ instructions=instructions,
51
52
  input=text,
52
53
  response_format=response_format
53
- )
54
-
55
- # Stream the bytes in chunks
56
- for chunk in stream.iter_bytes(chunk_size=1024 * 16): # 16KB chunks
57
- yield chunk
54
+ ) as stream:
55
+ # Stream the bytes in 16KB chunks
56
+ for chunk in stream.iter_bytes(chunk_size=1024 * 16):
57
+ yield chunk
58
58
 
59
59
  except Exception as e:
60
60
  print(f"Error in text_to_speech: {str(e)}")
@@ -66,7 +66,7 @@ class OpenAIAdapter(LLMProvider):
66
66
  print(f"Error in text_to_speech: {str(e)}")
67
67
  import traceback
68
68
  print(traceback.format_exc())
69
- yield f"I apologize, but I encountered an error converting text to speech: {str(e)}"
69
+ yield b"" # Return empty bytes on error
70
70
 
71
71
  async def transcribe_audio(
72
72
  self,
@@ -85,16 +85,14 @@ class OpenAIAdapter(LLMProvider):
85
85
  Transcript text chunks as they become available
86
86
  """
87
87
  try:
88
- stream = self.client.audio.transcriptions.create(
88
+ with self.client.audio.transcriptions.with_streaming_response.create(
89
89
  model=self.transcription_model,
90
90
  file=(f"file.{input_format}", audio_bytes),
91
91
  response_format="text",
92
- stream=True
93
- )
94
-
95
- for event in stream:
96
- if hasattr(event, 'text') and event.text:
97
- yield event.text
92
+ ) as stream:
93
+ # Stream the text in 16KB chunks
94
+ for chunk in stream.iter_text(chunk_size=1024 * 16):
95
+ yield chunk
98
96
 
99
97
  except Exception as e:
100
98
  print(f"Error in transcribe_audio: {str(e)}")
@@ -49,7 +49,7 @@ class SolanaAgent(SolanaAgentInterface):
49
49
  output_format: Literal["text", "audio"] = "text",
50
50
  audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
51
51
  "fable", "onyx", "nova", "sage", "shimmer"] = "nova",
52
- audio_instructions: Optional[str] = None,
52
+ audio_instructions: str = "You speak in a friendly and helpful manner.",
53
53
  audio_output_format: Literal['mp3', 'opus',
54
54
  'aac', 'flac', 'wav', 'pcm'] = "aac",
55
55
  audio_input_format: Literal[
@@ -66,7 +66,7 @@ class SolanaAgent(SolanaAgentInterface):
66
66
  prompt: Optional prompt for the agent
67
67
  output_format: Response format ("text" or "audio")
68
68
  audio_voice: Voice to use for audio output
69
- audio_instructions: Not used currently
69
+ audio_instructions: Audio voice instructions
70
70
  audio_output_format: Audio output format
71
71
  audio_input_format: Audio input format
72
72
  router: Optional routing service for processing
@@ -17,7 +17,7 @@ class SolanaAgent(ABC):
17
17
  output_format: Literal["text", "audio"] = "text",
18
18
  audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
19
19
  "fable", "onyx", "nova", "sage", "shimmer"] = "nova",
20
- audio_instructions: Optional[str] = None,
20
+ audio_instructions: str = "You speak in a friendly and helpful manner.",
21
21
  audio_output_format: Literal['mp3', 'opus',
22
22
  'aac', 'flac', 'wav', 'pcm'] = "aac",
23
23
  audio_input_format: Literal[
@@ -31,7 +31,7 @@ class LLMProvider(ABC):
31
31
  async def tts(
32
32
  self,
33
33
  text: str,
34
- instructions: str = "",
34
+ instructions: str = "You speak in a friendly and helpful manner.",
35
35
  voice: Literal["alloy", "ash", "ballad", "coral", "echo",
36
36
  "fable", "onyx", "nova", "sage", "shimmer"] = "nova",
37
37
  response_format: Literal['mp3', 'opus',
@@ -27,7 +27,7 @@ class AgentService(ABC):
27
27
  output_format: Literal["text", "audio"] = "text",
28
28
  audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
29
29
  "fable", "onyx", "nova", "sage", "shimmer"] = "nova",
30
- audio_instructions: Optional[str] = None,
30
+ audio_instructions: str = "You speak in a friendly and helpful manner.",
31
31
  audio_output_format: Literal['mp3', 'opus',
32
32
  'aac', 'flac', 'wav', 'pcm'] = "aac",
33
33
  audio_input_format: Literal[
@@ -13,7 +13,7 @@ class QueryService(ABC):
13
13
  output_format: Literal["text", "audio"] = "text",
14
14
  audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
15
15
  "fable", "onyx", "nova", "sage", "shimmer"] = "nova",
16
- audio_instructions: Optional[str] = None,
16
+ audio_instructions: str = "You speak in a friendly and helpful manner.",
17
17
  audio_output_format: Literal['mp3', 'opus',
18
18
  'aac', 'flac', 'wav', 'pcm'] = "aac",
19
19
  audio_input_format: Literal[
@@ -169,7 +169,7 @@ class AgentService(AgentServiceInterface):
169
169
  output_format: Literal["text", "audio"] = "text",
170
170
  audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
171
171
  "fable", "onyx", "nova", "sage", "shimmer"] = "nova",
172
- audio_instructions: Optional[str] = None,
172
+ audio_instructions: str = "You speak in a friendly and helpful manner.",
173
173
  audio_output_format: Literal['mp3', 'opus',
174
174
  'aac', 'flac', 'wav', 'pcm'] = "aac",
175
175
  audio_input_format: Literal[
@@ -276,7 +276,7 @@ class AgentService(AgentServiceInterface):
276
276
  tool_response += processed_chunk
277
277
 
278
278
  # Add to our complete text record and full audio buffer
279
- tool_response = self._remove_markdown(
279
+ tool_response = self._clean_for_audio(
280
280
  tool_response)
281
281
  complete_text_response += tool_response
282
282
  full_response_buffer += tool_response
@@ -318,8 +318,8 @@ class AgentService(AgentServiceInterface):
318
318
 
319
319
  # For audio output, now process the complete response
320
320
  if output_format == "audio" and full_response_buffer:
321
- # Clean markdown before TTS
322
- full_response_buffer = self._remove_markdown(
321
+ # Clean text before TTS
322
+ full_response_buffer = self._clean_for_audio(
323
323
  full_response_buffer)
324
324
 
325
325
  # Process the entire response with TTS
@@ -427,14 +427,14 @@ class AgentService(AgentServiceInterface):
427
427
  - Use exact tool names as shown in AVAILABLE TOOLS
428
428
  """
429
429
 
430
- def _remove_markdown(self, text: str) -> str:
431
- """Remove Markdown formatting and links from text.
430
+ def _clean_for_audio(self, text: str) -> str:
431
+ """Remove Markdown formatting, emojis, and non-pronounceable characters from text.
432
432
 
433
433
  Args:
434
- text: Input text with potential Markdown formatting
434
+ text: Input text with potential Markdown formatting and special characters
435
435
 
436
436
  Returns:
437
- Clean text without Markdown formatting
437
+ Clean text without Markdown, emojis, and special characters
438
438
  """
439
439
  import re
440
440
 
@@ -469,4 +469,34 @@ class AgentService(AgentServiceInterface):
469
469
  # Remove multiple consecutive newlines (keep just one)
470
470
  text = re.sub(r'\n{3,}', '\n\n', text)
471
471
 
472
+ # Remove emojis and other non-pronounceable characters
473
+ # Common emoji Unicode ranges
474
+ emoji_pattern = re.compile(
475
+ "["
476
+ "\U0001F600-\U0001F64F" # emoticons
477
+ "\U0001F300-\U0001F5FF" # symbols & pictographs
478
+ "\U0001F680-\U0001F6FF" # transport & map symbols
479
+ "\U0001F700-\U0001F77F" # alchemical symbols
480
+ "\U0001F780-\U0001F7FF" # Geometric Shapes
481
+ "\U0001F800-\U0001F8FF" # Supplemental Arrows-C
482
+ "\U0001F900-\U0001F9FF" # Supplemental Symbols and Pictographs
483
+ "\U0001FA00-\U0001FA6F" # Chess Symbols
484
+ "\U0001FA70-\U0001FAFF" # Symbols and Pictographs Extended-A
485
+ "\U00002702-\U000027B0" # Dingbats
486
+ "\U000024C2-\U0000257F" # Enclosed characters
487
+ "\U00002600-\U000026FF" # Miscellaneous Symbols
488
+ "\U00002700-\U000027BF" # Dingbats
489
+ "\U0000FE00-\U0000FE0F" # Variation Selectors
490
+ "\U0001F1E0-\U0001F1FF" # Flags (iOS)
491
+ "]+",
492
+ flags=re.UNICODE
493
+ )
494
+ text = emoji_pattern.sub(r' ', text)
495
+
496
+ # Replace special characters that can cause issues with TTS
497
+ text = re.sub(r'[^\w\s\.\,\;\:\?\!\'\"\-\(\)]', ' ', text)
498
+
499
+ # Replace multiple spaces with a single space
500
+ text = re.sub(r'\s+', ' ', text)
501
+
472
502
  return text.strip()
@@ -41,7 +41,7 @@ class QueryService(QueryServiceInterface):
41
41
  output_format: Literal["text", "audio"] = "text",
42
42
  audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
43
43
  "fable", "onyx", "nova", "sage", "shimmer"] = "nova",
44
- audio_instructions: Optional[str] = None,
44
+ audio_instructions: str = "You speak in a friendly and helpful manner.",
45
45
  audio_output_format: Literal['mp3', 'opus',
46
46
  'aac', 'flac', 'wav', 'pcm'] = "aac",
47
47
  audio_input_format: Literal[
@@ -58,7 +58,7 @@ class QueryService(QueryServiceInterface):
58
58
  query: Text query or audio bytes
59
59
  output_format: Response format ("text" or "audio")
60
60
  audio_voice: Voice for TTS (text-to-speech)
61
- audio_instructions: Optional instructions for TTS
61
+ audio_instructions: Audio voice instructions
62
62
  audio_output_format: Audio output format
63
63
  audio_input_format: Audio input format
64
64
  prompt: Optional prompt for the agent
@@ -84,7 +84,8 @@ class QueryService(QueryServiceInterface):
84
84
  async for chunk in self.agent_service.llm_provider.tts(
85
85
  text=response,
86
86
  voice=audio_voice,
87
- response_format=audio_output_format
87
+ response_format=audio_output_format,
88
+ instructions=audio_instructions,
88
89
  ):
89
90
  yield chunk
90
91
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: solana-agent
3
- Version: 22.0.1
3
+ Version: 22.0.3
4
4
  Summary: Agentic IQ
5
5
  License: MIT
6
6
  Keywords: ai,openai,ai agents,agi
@@ -249,6 +249,15 @@ async for response in solana_agent.process("user123", "Write me a poem.", intern
249
249
  print(response, end="")
250
250
  ```
251
251
 
252
+ ### Customize Audio Voice
253
+
254
+ This is an audio to audio example using the `audio_instructions` parameter.
255
+
256
+ ```python
257
+ async for response in solana_agent.process("user123", audio_content, output_format="audio", audio_voice="nova", audio_input_format="webm", audio_output_format="aac", audio_instructions="You speak with an American southern accent"):
258
+ print(response, end="")
259
+ ```
260
+
252
261
  ## Tools
253
262
 
254
263
  Tools can be used from plugins like Solana Agent Kit (sakit) or via custom inline tools. Tools available via plugins integrate automatically with Solana Agent.
@@ -1,22 +1,22 @@
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=PsSkMrsSqZzXAL3NcQ9Zz7UCtyJYU0USvZ7uTD_I8NI,5629
3
+ solana_agent/adapters/llm_adapter.py,sha256=ReCVQH0X0hf5NpLqEMESft5LZtPj3gDNIOBiZpClqzo,5737
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
- solana_agent/client/solana_agent.py,sha256=8mu0OdLBQnZXKS2mFrWvvY_4bykzhT73oyIxs9tmJvY,5318
6
+ solana_agent/client/solana_agent.py,sha256=-bIVaE5p6He4d5VRzYhlAgkMzhql4EVFsujjnoweh2o,5355
7
7
  solana_agent/domains/__init__.py,sha256=HiC94wVPRy-QDJSSRywCRrhrFfTBeHjfi5z-QfZv46U,168
8
8
  solana_agent/domains/agent.py,sha256=WTo-pEc66V6D_35cpDE-kTsw1SJM-dtylPZ7em5em7Q,2659
9
9
  solana_agent/domains/routing.py,sha256=UDlgTjUoC9xIBVYu_dnf9-KG_bBgdEXAv_UtDOrYo0w,650
10
10
  solana_agent/factories/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  solana_agent/factories/agent_factory.py,sha256=mJQb1G0-gebizZvSVHm4NAxRMB1kemm2w_BAcYlN15Y,5496
12
12
  solana_agent/interfaces/__init__.py,sha256=IQs1WIM1FeKP1-kY2FEfyhol_dB-I-VAe2rD6jrVF6k,355
13
- solana_agent/interfaces/client/client.py,sha256=RbZWS_YaAyav56cODECMNkYL0MJwA_8bFeUreZp26qo,1697
13
+ solana_agent/interfaces/client/client.py,sha256=btAt-bVVxsunA6rcbn0jqVmZ1JMxcF_u95CIXByO7fk,1728
14
14
  solana_agent/interfaces/plugins/plugins.py,sha256=T8HPBsekmzVwfU_Rizp-vtzAeYkMlKMYD7U9d0Wjq9c,3338
15
15
  solana_agent/interfaces/providers/data_storage.py,sha256=NqGeFvAzhz9rr-liLPRNCGjooB2EIhe-EVsMmX__b0M,1658
16
- solana_agent/interfaces/providers/llm.py,sha256=Fy7_iTI8sez2NVeE9lDed4W5cXx95HRy0ctEpIqr5N0,1548
16
+ solana_agent/interfaces/providers/llm.py,sha256=_sbgSs3Sy1QAeFCB_jzw_Rjpq-N5wBY5qt6tmFYD9K4,1591
17
17
  solana_agent/interfaces/providers/memory.py,sha256=oNOH8WZXVW8assDigIWZAWiwkxbpDiKupxA2RB6tQvQ,1010
18
- solana_agent/interfaces/services/agent.py,sha256=7HOGcvvHTxeK-dMlqw460yqKwGd72JokhDIr3kzroVg,2120
19
- solana_agent/interfaces/services/query.py,sha256=PGW2w60R615og28Bw6sS1cCcBN_26KkkOsYDYclS1KQ,1347
18
+ solana_agent/interfaces/services/agent.py,sha256=mvXl5JLiJJz0ajjVuntR-Sz8geRGs9RVqOEBsf8VzzE,2151
19
+ solana_agent/interfaces/services/query.py,sha256=rKIYjHBeOaFFawFYduJbMRp7imYg-uRElZoizBgua00,1378
20
20
  solana_agent/interfaces/services/routing.py,sha256=UzJC-z-Q9puTWPFGEo2_CAhIxuxP5IRnze7S66NSrsI,397
21
21
  solana_agent/plugins/__init__.py,sha256=coZdgJKq1ExOaj6qB810i3rEhbjdVlrkN76ozt_Ojgo,193
22
22
  solana_agent/plugins/manager.py,sha256=Il49hXeqvu0b02pURNNp7mY8kp9_sqpi_vJIWBW5Hc0,5044
@@ -26,10 +26,10 @@ solana_agent/plugins/tools/auto_tool.py,sha256=DgES_cZ6xKSf_HJpFINpvJxrjVlk5oeqa
26
26
  solana_agent/repositories/__init__.py,sha256=fP83w83CGzXLnSdq-C5wbw9EhWTYtqE2lQTgp46-X_4,163
27
27
  solana_agent/repositories/memory.py,sha256=mrpmNSQ0D_eLebNY-cBqtecVVpIGXE7s9jCzOWEAuR4,6984
28
28
  solana_agent/services/__init__.py,sha256=ab_NXJmwYUCmCrCzuTlZ47bJZINW0Y0F5jfQ9OovidU,163
29
- solana_agent/services/agent.py,sha256=uLZvMl8U40H-Lbxsf6PFR4SSfggjByBUoumvB1Afduo,18441
30
- solana_agent/services/query.py,sha256=gUIMJaTcGUjn7TuwJHE-CHMjQIdcYUNoxqJ3duE-QUg,11278
29
+ solana_agent/services/agent.py,sha256=ODHI66S2Y65lHrE6Kbe0zNORiz16oaMNGT3x6NoKDKo,19909
30
+ solana_agent/services/query.py,sha256=os_LRkDIwXQuWW_zJMtm__n0Lvi-AvItdanpCs1bXv0,11362
31
31
  solana_agent/services/routing.py,sha256=PMCSG5m3uLMaHMj3dxNvNfcFZaeaDi7kMr7AEBCzwDE,6499
32
- solana_agent-22.0.1.dist-info/LICENSE,sha256=BnSRc-NSFuyF2s496l_4EyrwAP6YimvxWcjPiJ0J7g4,1057
33
- solana_agent-22.0.1.dist-info/METADATA,sha256=iUmnx3K1S69RYYoBNXE8hYBfXugafCX3r_ZMKOtJEjY,14503
34
- solana_agent-22.0.1.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
35
- solana_agent-22.0.1.dist-info/RECORD,,
32
+ solana_agent-22.0.3.dist-info/LICENSE,sha256=BnSRc-NSFuyF2s496l_4EyrwAP6YimvxWcjPiJ0J7g4,1057
33
+ solana_agent-22.0.3.dist-info/METADATA,sha256=njD8XhVplqd_P6MtEvMHk88WvXQf7rs2nGuMyq0p4-M,14882
34
+ solana_agent-22.0.3.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
35
+ solana_agent-22.0.3.dist-info/RECORD,,