solana-agent 17.1.9__tar.gz → 17.1.11__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-17.1.9 → solana_agent-17.1.11}/PKG-INFO +1 -1
  2. {solana_agent-17.1.9 → solana_agent-17.1.11}/pyproject.toml +1 -1
  3. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/plugins/registry.py +9 -7
  4. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/services/agent.py +52 -111
  5. {solana_agent-17.1.9 → solana_agent-17.1.11}/LICENSE +0 -0
  6. {solana_agent-17.1.9 → solana_agent-17.1.11}/README.md +0 -0
  7. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/__init__.py +0 -0
  8. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/adapters/__init__.py +0 -0
  9. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/adapters/llm_adapter.py +0 -0
  10. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/adapters/mongodb_adapter.py +0 -0
  11. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/client/__init__.py +0 -0
  12. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/client/solana_agent.py +0 -0
  13. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/domains/__init__.py +0 -0
  14. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/domains/agent.py +0 -0
  15. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/domains/routing.py +0 -0
  16. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/factories/__init__.py +0 -0
  17. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/factories/agent_factory.py +0 -0
  18. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/interfaces/__init__.py +0 -0
  19. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/interfaces/client/client.py +0 -0
  20. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/interfaces/plugins/plugins.py +0 -0
  21. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/interfaces/providers/data_storage.py +0 -0
  22. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/interfaces/providers/llm.py +0 -0
  23. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/interfaces/providers/memory.py +0 -0
  24. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/interfaces/services/agent.py +0 -0
  25. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/interfaces/services/query.py +0 -0
  26. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/interfaces/services/routing.py +0 -0
  27. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/plugins/__init__.py +0 -0
  28. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/plugins/manager.py +0 -0
  29. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/plugins/tools/__init__.py +0 -0
  30. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/plugins/tools/auto_tool.py +0 -0
  31. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/repositories/__init__.py +0 -0
  32. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/repositories/memory.py +0 -0
  33. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/services/__init__.py +0 -0
  34. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/services/query.py +0 -0
  35. {solana_agent-17.1.9 → solana_agent-17.1.11}/solana_agent/services/routing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: solana-agent
3
- Version: 17.1.9
3
+ Version: 17.1.11
4
4
  Summary: Agentic IQ
5
5
  License: MIT
6
6
  Keywords: ai,openai,ai agents,agi
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "solana-agent"
3
- version = "17.1.9"
3
+ version = "17.1.11"
4
4
  description = "Agentic IQ"
5
5
  authors = ["Bevan Hunt <bevan@bevanhunt.com>"]
6
6
  license = "MIT"
@@ -42,15 +42,17 @@ class ToolRegistry(ToolRegistryInterface):
42
42
  f"Error: Tool {tool_name} is not registered. Available tools: {list(self._tools.keys())}")
43
43
  return False
44
44
 
45
+ # Initialize agent's tool list if not exists
45
46
  if agent_name not in self._agent_tools:
46
- self._agent_tools[agent_name] = []
47
+ self._agent_tools[agent_name] = [tool_name]
48
+ elif tool_name not in self._agent_tools[agent_name]:
49
+ # Add new tool to existing list
50
+ self._agent_tools[agent_name] = [
51
+ *self._agent_tools[agent_name], tool_name]
47
52
 
48
- if tool_name not in self._agent_tools[agent_name]:
49
- self._agent_tools[agent_name].append(tool_name)
50
- print(
51
- f"Successfully assigned tool {tool_name} to agent {agent_name}")
52
- print(
53
- f"Agent {agent_name} now has access to: {self._agent_tools[agent_name]}")
53
+ print(f"Successfully assigned tool {tool_name} to agent {agent_name}")
54
+ print(
55
+ f"Agent {agent_name} now has access to: {self._agent_tools[agent_name]}")
54
56
 
55
57
  return True
56
58
 
@@ -241,8 +241,6 @@ class AgentService(AgentServiceInterface):
241
241
  is_json = False
242
242
  text_buffer = ""
243
243
 
244
- print("\n=== Starting Response Generation ===")
245
-
246
244
  # Generate and stream response
247
245
  async for chunk in self.llm_provider.generate_text(
248
246
  prompt=query_text,
@@ -260,54 +258,40 @@ class AgentService(AgentServiceInterface):
260
258
  try:
261
259
  # Try to parse complete JSON
262
260
  data = json.loads(json_buffer)
263
- print(
264
- f"Successfully parsed JSON: {json.dumps(data, indent=2)}")
265
261
 
266
262
  # Valid JSON found, handle it
267
- if "tool_calls" in data: # Now looking for tool_calls array
268
- tool_results = []
269
- async for tool_result in self._handle_multiple_tool_calls(
263
+ if "tool_call" in data:
264
+ # Process tool call with existing method
265
+ response_text = await self._handle_tool_call(
270
266
  agent_name=agent_name,
271
267
  json_chunk=json_buffer
272
- ):
273
- tool_results.append(tool_result)
274
-
275
- # Combine results and create a new prompt with clear instructions
276
- tool_response = "\n".join(tool_results)
277
- process_prompt = f"""
278
- {tool_response}
279
-
280
- IMPORTANT INSTRUCTIONS:
281
- 1. Maintain ALL factual details
282
- 2. Include ALL statistics, numbers, and specific data points
283
- 3. Use direct quotes where relevant
284
- 4. Keep ALL source citations and references
285
- 5. DO NOT omit or summarize away important details
286
- 6. DO NOT add any information not present in the results
287
- 7. DO NOT make any new tool calls or return JSON
288
- """
289
-
290
- # Process combined results through LLM with modified system prompt
291
- summary_system_prompt = self.get_agent_system_prompt(agent_name) + \
292
- "\n DO NOT make any tool calls or return JSON. Present ALL facts and maintain ALL details from the source material."
268
+ )
269
+
270
+ system_prompt = self.get_agent_system_prompt(agent_name) + \
271
+ "\n DO NOT make any tool calls or return JSON."
293
272
 
273
+ # Collect all processed text first
274
+ processed_text = ""
294
275
  async for processed_chunk in self.llm_provider.generate_text(
295
- prompt=process_prompt,
296
- system_prompt=summary_system_prompt,
276
+ prompt=response_text,
277
+ system_prompt=system_prompt,
297
278
  ):
298
- # Add to complete response
299
- complete_text_response += processed_chunk
300
-
301
- # Output response based on format
302
- if output_format == "audio":
303
- async for audio_chunk in self.llm_provider.tts(
304
- text=processed_chunk,
305
- voice=audio_voice,
306
- response_format=audio_output_format
307
- ):
308
- yield audio_chunk
309
- else:
279
+ processed_text += processed_chunk
280
+ # For text output, yield chunks as they come
281
+ if output_format == "text":
310
282
  yield processed_chunk
283
+
284
+ # Add to complete response
285
+ complete_text_response += processed_text
286
+
287
+ # For audio output, process the complete text
288
+ if output_format == "audio":
289
+ async for audio_chunk in self.llm_provider.tts(
290
+ text=processed_text,
291
+ voice=audio_voice,
292
+ response_format=audio_output_format
293
+ ):
294
+ yield audio_chunk
311
295
  else:
312
296
  # For non-tool JSON, still capture the text
313
297
  complete_text_response += json_buffer
@@ -383,6 +367,30 @@ class AgentService(AgentServiceInterface):
383
367
  import traceback
384
368
  print(traceback.format_exc())
385
369
 
370
+ async def _handle_tool_call(
371
+ self,
372
+ agent_name: str,
373
+ json_chunk: str,
374
+ ) -> str:
375
+ """Handle tool calls and return formatted response."""
376
+ try:
377
+ data = json.loads(json_chunk)
378
+ if "tool_call" in data:
379
+ tool_data = data["tool_call"]
380
+ tool_name = tool_data.get("name")
381
+ parameters = tool_data.get("parameters", {})
382
+
383
+ if tool_name:
384
+ result = self.execute_tool(
385
+ agent_name, tool_name, parameters)
386
+ if result.get("status") == "success":
387
+ return result.get("result", "")
388
+ else:
389
+ return f"I apologize, but I encountered an issue: {result.get('message', 'Unknown error')}"
390
+ return json_chunk
391
+ except json.JSONDecodeError:
392
+ return json_chunk
393
+
386
394
  def _get_tool_usage_prompt(self, agent_name: str) -> str:
387
395
  """Generate JSON-based instructions for tool usage."""
388
396
  # Get tools assigned to this agent
@@ -394,94 +402,27 @@ class AgentService(AgentServiceInterface):
394
402
  available_tool_names = [tool.get("name", "") for tool in tools]
395
403
  tools_json = json.dumps(tools, indent=2)
396
404
 
397
- # Create tool example if search is available
398
- tool_example = ""
399
- if "search_internet" in available_tool_names:
400
- tool_example = """
401
- For latest news query:
402
- {
403
- "tool_calls": [{
404
- "name": "search_internet",
405
- "parameters": {
406
- "query": "latest Solana blockchain news March 2025"
407
- }
408
- }]
409
- }"""
410
-
411
405
  return f"""
412
406
  AVAILABLE TOOLS:
413
407
  {tools_json}
414
408
 
415
409
  TOOL USAGE FORMAT:
416
410
  {{
417
- "tool_calls": [{{
411
+ "tool_call": {{
418
412
  "name": "<one_of:{', '.join(available_tool_names)}>",
419
413
  "parameters": {{
420
414
  // parameters as specified in tool definition above
421
415
  }}
422
- }}]
416
+ }}
423
417
  }}
424
418
 
425
- {tool_example if tool_example else ''}
426
-
427
419
  RESPONSE RULES:
428
420
  1. For tool usage:
429
421
  - Only use tools from the AVAILABLE TOOLS list above
430
422
  - Follow the exact parameter format shown in the tool definition
431
- - Include "March 2025" in any search queries for current information
432
423
 
433
424
  2. Format Requirements:
434
425
  - Return ONLY the JSON object for tool calls
435
426
  - No explanation text before or after
436
427
  - Use exact tool names as shown in AVAILABLE TOOLS
437
428
  """
438
-
439
- async def _handle_multiple_tool_calls(
440
- self,
441
- agent_name: str,
442
- json_chunk: str,
443
- ) -> AsyncGenerator[str, None]:
444
- """Handle multiple tool calls concurrently and yield results as they complete."""
445
- try:
446
- data = json.loads(json_chunk)
447
- if "tool_calls" not in data:
448
- yield json_chunk
449
- return
450
-
451
- tool_calls = data["tool_calls"]
452
-
453
- if not isinstance(tool_calls, list):
454
- print("Error: tool_calls is not a list")
455
- yield "Error: 'tool_calls' must be an array of tool calls."
456
- return
457
-
458
- # Define individual tool execution coroutine
459
- async def execute_single_tool(tool_info):
460
- tool_name = tool_info.get("name")
461
- parameters = tool_info.get("parameters", {})
462
- print(f"\nExecuting tool: {tool_name}")
463
- print(f"With parameters: {parameters}")
464
-
465
- if not tool_name:
466
- return f"Error: Missing tool name in tool call."
467
-
468
- result = self.execute_tool(agent_name, tool_name, parameters)
469
-
470
- if result.get("status") == "success":
471
- return f"Result from {tool_name}: {result.get('result', '')}"
472
- else:
473
- return f"Error from {tool_name}: {result.get('message', 'Unknown error')}"
474
-
475
- # Execute all tool calls concurrently
476
- tasks = [execute_single_tool(tool_call)
477
- for tool_call in tool_calls]
478
- for task in asyncio.as_completed(tasks):
479
- result = await task
480
- yield result
481
-
482
- except json.JSONDecodeError:
483
- yield "Error: Could not parse tool calls JSON."
484
- except Exception as e:
485
- import traceback
486
- print(traceback.format_exc())
487
- yield f"Error processing tool calls: {str(e)}"
File without changes
File without changes