praisonaiagents 0.0.133__py3-none-any.whl → 0.0.135__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.
@@ -2,6 +2,7 @@ import logging
2
2
  import os
3
3
  import warnings
4
4
  import re
5
+ import inspect
5
6
  from typing import Any, Dict, List, Optional, Union, Literal, Callable
6
7
  from pydantic import BaseModel
7
8
  import time
@@ -379,6 +380,65 @@ class LLM:
379
380
 
380
381
  return function_name, arguments, tool_call_id
381
382
 
383
+ def _validate_and_filter_ollama_arguments(self, function_name: str, arguments: Dict[str, Any], available_tools: List) -> Dict[str, Any]:
384
+ """
385
+ Validate and filter tool call arguments for Ollama provider.
386
+
387
+ Ollama sometimes generates tool calls with mixed parameters where arguments
388
+ from different functions are combined. This method validates arguments against
389
+ the actual function signature and removes invalid parameters.
390
+
391
+ Args:
392
+ function_name: Name of the function to call
393
+ arguments: Arguments provided in the tool call
394
+ available_tools: List of available tool functions
395
+
396
+ Returns:
397
+ Filtered arguments dictionary with only valid parameters
398
+ """
399
+ if not available_tools:
400
+ logging.debug(f"[OLLAMA_FIX] No available tools provided for validation")
401
+ return arguments
402
+
403
+ # Find the target function
404
+ target_function = None
405
+ for tool in available_tools:
406
+ tool_name = getattr(tool, '__name__', str(tool))
407
+ if tool_name == function_name:
408
+ target_function = tool
409
+ break
410
+
411
+ if not target_function:
412
+ logging.debug(f"[OLLAMA_FIX] Function {function_name} not found in available tools")
413
+ return arguments
414
+
415
+ try:
416
+ # Get function signature
417
+ sig = inspect.signature(target_function)
418
+ valid_params = set(sig.parameters.keys())
419
+
420
+ # Filter arguments to only include valid parameters
421
+ filtered_args = {}
422
+ invalid_params = []
423
+
424
+ for param_name, param_value in arguments.items():
425
+ if param_name in valid_params:
426
+ filtered_args[param_name] = param_value
427
+ else:
428
+ invalid_params.append(param_name)
429
+
430
+ if invalid_params:
431
+ logging.debug(f"[OLLAMA_FIX] Function {function_name} received invalid parameters: {invalid_params}")
432
+ logging.debug(f"[OLLAMA_FIX] Valid parameters for {function_name}: {list(valid_params)}")
433
+ logging.debug(f"[OLLAMA_FIX] Original arguments: {arguments}")
434
+ logging.debug(f"[OLLAMA_FIX] Filtered arguments: {filtered_args}")
435
+
436
+ return filtered_args
437
+
438
+ except Exception as e:
439
+ logging.debug(f"[OLLAMA_FIX] Error validating arguments for {function_name}: {e}")
440
+ return arguments
441
+
382
442
  def _needs_system_message_skip(self) -> bool:
383
443
  """Check if this model requires skipping system messages"""
384
444
  if not self.model:
@@ -542,6 +602,7 @@ class LLM:
542
602
  - Lists of pre-formatted tools
543
603
  - Callable functions
544
604
  - String function names
605
+ - Gemini internal tools ({"googleSearch": {}}, {"urlContext": {}}, {"codeExecution": {}})
545
606
 
546
607
  Args:
547
608
  tools: List of tools in various formats
@@ -588,6 +649,15 @@ class LLM:
588
649
  tool_def = self._generate_tool_definition(tool)
589
650
  if tool_def:
590
651
  formatted_tools.append(tool_def)
652
+ # Handle Gemini internal tools (e.g., {"googleSearch": {}}, {"urlContext": {}}, {"codeExecution": {}})
653
+ elif isinstance(tool, dict) and len(tool) == 1:
654
+ tool_name = next(iter(tool.keys()))
655
+ gemini_internal_tools = {'googleSearch', 'urlContext', 'codeExecution'}
656
+ if tool_name in gemini_internal_tools:
657
+ logging.debug(f"Using Gemini internal tool: {tool_name}")
658
+ formatted_tools.append(tool)
659
+ else:
660
+ logging.debug(f"Skipping unknown tool: {tool_name}")
591
661
  else:
592
662
  logging.debug(f"Skipping tool of unsupported type: {type(tool)}")
593
663
 
@@ -952,6 +1022,10 @@ class LLM:
952
1022
  is_ollama = self._is_ollama_provider()
953
1023
  function_name, arguments, tool_call_id = self._extract_tool_call_info(tool_call, is_ollama)
954
1024
 
1025
+ # Validate and filter arguments for Ollama provider
1026
+ if is_ollama and tools:
1027
+ arguments = self._validate_and_filter_ollama_arguments(function_name, arguments, tools)
1028
+
955
1029
  logging.debug(f"[TOOL_EXEC_DEBUG] About to execute tool {function_name} with args: {arguments}")
956
1030
  tool_result = execute_tool_fn(function_name, arguments)
957
1031
  logging.debug(f"[TOOL_EXEC_DEBUG] Tool execution result: {tool_result}")
@@ -1603,6 +1677,10 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
1603
1677
  is_ollama = self._is_ollama_provider()
1604
1678
  function_name, arguments, tool_call_id = self._extract_tool_call_info(tool_call, is_ollama)
1605
1679
 
1680
+ # Validate and filter arguments for Ollama provider
1681
+ if is_ollama and tools:
1682
+ arguments = self._validate_and_filter_ollama_arguments(function_name, arguments, tools)
1683
+
1606
1684
  tool_result = await execute_tool_fn(function_name, arguments)
1607
1685
  tool_results.append(tool_result) # Store the result
1608
1686
 
@@ -104,4 +104,27 @@ def supports_streaming_with_tools(model_name: str) -> bool:
104
104
  """
105
105
  # For now, use the same logic as structured outputs
106
106
  # In the future, this could be a separate list if needed
107
- return supports_structured_outputs(model_name)
107
+ return supports_structured_outputs(model_name)
108
+
109
+
110
+ # Supported Gemini internal tools
111
+ GEMINI_INTERNAL_TOOLS = {'googleSearch', 'urlContext', 'codeExecution'}
112
+
113
+
114
+ def is_gemini_internal_tool(tool) -> bool:
115
+ """
116
+ Check if a tool is a Gemini internal tool and should be included in formatted tools.
117
+
118
+ Gemini internal tools are single-key dictionaries with specific tool names.
119
+ Examples: {"googleSearch": {}}, {"urlContext": {}}, {"codeExecution": {}}
120
+
121
+ Args:
122
+ tool: The tool to check
123
+
124
+ Returns:
125
+ bool: True if the tool is a recognized Gemini internal tool, False otherwise
126
+ """
127
+ if isinstance(tool, dict) and len(tool) == 1:
128
+ tool_name = next(iter(tool.keys()))
129
+ return tool_name in GEMINI_INTERNAL_TOOLS
130
+ return False
@@ -360,6 +360,7 @@ class OpenAIClient:
360
360
  - Callable functions
361
361
  - String function names
362
362
  - MCP tools
363
+ - Gemini internal tools ({"googleSearch": {}}, {"urlContext": {}}, {"codeExecution": {}})
363
364
 
364
365
  Args:
365
366
  tools: List of tools in various formats
@@ -404,6 +405,15 @@ class OpenAIClient:
404
405
  tool_def = self._generate_tool_definition_from_name(tool)
405
406
  if tool_def:
406
407
  formatted_tools.append(tool_def)
408
+ # Handle Gemini internal tools (e.g., {"googleSearch": {}}, {"urlContext": {}}, {"codeExecution": {}})
409
+ elif isinstance(tool, dict) and len(tool) == 1:
410
+ tool_name = next(iter(tool.keys()))
411
+ gemini_internal_tools = {'googleSearch', 'urlContext', 'codeExecution'}
412
+ if tool_name in gemini_internal_tools:
413
+ logging.debug(f"Using Gemini internal tool: {tool_name}")
414
+ formatted_tools.append(tool)
415
+ else:
416
+ logging.debug(f"Skipping unknown tool: {tool_name}")
407
417
  else:
408
418
  logging.debug(f"Skipping tool of unsupported type: {type(tool)}")
409
419
 
@@ -1,13 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: praisonaiagents
3
- Version: 0.0.133
3
+ Version: 0.0.135
4
4
  Summary: Praison AI agents for completing complex tasks with Self Reflection Agents
5
5
  Author: Mervin Praison
6
6
  Requires-Python: >=3.10
7
7
  Requires-Dist: pydantic
8
8
  Requires-Dist: rich
9
9
  Requires-Dist: openai
10
- Requires-Dist: mcp>=1.6.0
11
10
  Requires-Dist: posthog>=3.0.0
12
11
  Requires-Dist: aiohttp>=3.8.0
13
12
  Provides-Extra: mcp
@@ -17,10 +17,10 @@ praisonaiagents/knowledge/__init__.py,sha256=xL1Eh-a3xsHyIcU4foOWF-JdWYIYBALJH9b
17
17
  praisonaiagents/knowledge/chunking.py,sha256=G6wyHa7_8V0_7VpnrrUXbEmUmptlT16ISJYaxmkSgmU,7678
18
18
  praisonaiagents/knowledge/knowledge.py,sha256=-di_h9HxXQfAhTMMerhK16tfw8DtUndp44TGkBOzkZs,15539
19
19
  praisonaiagents/llm/__init__.py,sha256=tHvWq5mv4K4MhWr0s6rqox8UnJ5RK0kXhYuD40WkZQA,1747
20
- praisonaiagents/llm/llm.py,sha256=UAoezf_FF435xNCpOq1TtuEngInIobgBGZiLSX2d8Wg,122381
21
- praisonaiagents/llm/model_capabilities.py,sha256=MrEDLpYk9U_xzvXXIKYD4-bnNQg_W4bnaoTPyBUHfcs,3231
20
+ praisonaiagents/llm/llm.py,sha256=trPfrRKfwG4z2bx26gAbdfDrAIIqU7Vdqq3pAyCqO-g,126191
21
+ praisonaiagents/llm/model_capabilities.py,sha256=cxOvZcjZ_PIEpUYKn3S2FMyypfOSfbGpx4vmV7Y5vhI,3967
22
22
  praisonaiagents/llm/model_router.py,sha256=Jy2pShlkLxqXF3quz-MRB3-6L9vaUSgUrf2YJs_Tsg0,13995
23
- praisonaiagents/llm/openai_client.py,sha256=6KANw9SNiglvfJvTcpDPZjuTKG6cThD1t-ZqgKvmZiw,45356
23
+ praisonaiagents/llm/openai_client.py,sha256=EgWjkDjVpnLKCp1gBFjccDGyqR1anOcSYJYCo45fuEI,46046
24
24
  praisonaiagents/mcp/__init__.py,sha256=ibbqe3_7XB7VrIcUcetkZiUZS1fTVvyMy_AqCSFG8qc,240
25
25
  praisonaiagents/mcp/mcp.py,sha256=T0G0rQotHxk9qTnG1tjQLr4c0BUSLnEqz9sIMx4F954,21598
26
26
  praisonaiagents/mcp/mcp_http_stream.py,sha256=Yh-69eIlLQS_M0bd__y7NzSjOqqX6R8Ed4eJQw6xXgg,18314
@@ -57,7 +57,7 @@ praisonaiagents/tools/xml_tools.py,sha256=iYTMBEk5l3L3ryQ1fkUnNVYK-Nnua2Kx2S0dxN
57
57
  praisonaiagents/tools/yaml_tools.py,sha256=uogAZrhXV9O7xvspAtcTfpKSQYL2nlOTvCQXN94-G9A,14215
58
58
  praisonaiagents/tools/yfinance_tools.py,sha256=s2PBj_1v7oQnOobo2fDbQBACEHl61ftG4beG6Z979ZE,8529
59
59
  praisonaiagents/tools/train/data/generatecot.py,sha256=H6bNh-E2hqL5MW6kX3hqZ05g9ETKN2-kudSjiuU_SD8,19403
60
- praisonaiagents-0.0.133.dist-info/METADATA,sha256=rMgd4wWk6Eb5J05cO9MYVVDVYwxwoFum8Zj3AqJ8DmE,1699
61
- praisonaiagents-0.0.133.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
62
- praisonaiagents-0.0.133.dist-info/top_level.txt,sha256=_HsRddrJ23iDx5TTqVUVvXG2HeHBL5voshncAMDGjtA,16
63
- praisonaiagents-0.0.133.dist-info/RECORD,,
60
+ praisonaiagents-0.0.135.dist-info/METADATA,sha256=NsRPw0-Eabr1fhnHuTCH4yWtpwSX8sRfpFfeC6tor-o,1673
61
+ praisonaiagents-0.0.135.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
62
+ praisonaiagents-0.0.135.dist-info/top_level.txt,sha256=_HsRddrJ23iDx5TTqVUVvXG2HeHBL5voshncAMDGjtA,16
63
+ praisonaiagents-0.0.135.dist-info/RECORD,,