praisonaiagents 0.0.108__py3-none-any.whl → 0.0.110__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.
- praisonaiagents/__init__.py +6 -0
- praisonaiagents/agent/__init__.py +2 -1
- praisonaiagents/agent/agent.py +79 -3
- praisonaiagents/agent/handoff.py +317 -0
- praisonaiagents/llm/llm.py +217 -68
- praisonaiagents/mcp/mcp.py +27 -7
- praisonaiagents/memory/memory.py +48 -0
- praisonaiagents/tools/duckdb_tools.py +47 -16
- praisonaiagents/tools/file_tools.py +52 -10
- praisonaiagents/tools/python_tools.py +84 -4
- praisonaiagents/tools/shell_tools.py +18 -8
- praisonaiagents/tools/spider_tools.py +55 -0
- {praisonaiagents-0.0.108.dist-info → praisonaiagents-0.0.110.dist-info}/METADATA +1 -1
- {praisonaiagents-0.0.108.dist-info → praisonaiagents-0.0.110.dist-info}/RECORD +16 -15
- {praisonaiagents-0.0.108.dist-info → praisonaiagents-0.0.110.dist-info}/WHEEL +0 -0
- {praisonaiagents-0.0.108.dist-info → praisonaiagents-0.0.110.dist-info}/top_level.txt +0 -0
@@ -46,20 +46,100 @@ class PythonTools:
|
|
46
46
|
timeout: int = 30,
|
47
47
|
max_output_size: int = 10000
|
48
48
|
) -> Dict[str, Any]:
|
49
|
-
"""Execute Python code safely."""
|
49
|
+
"""Execute Python code safely with restricted builtins."""
|
50
50
|
try:
|
51
|
-
#
|
51
|
+
# Create safe builtins - restricted set of functions
|
52
|
+
safe_builtins = {
|
53
|
+
# Basic functions
|
54
|
+
'print': print,
|
55
|
+
'len': len,
|
56
|
+
'range': range,
|
57
|
+
'enumerate': enumerate,
|
58
|
+
'zip': zip,
|
59
|
+
'map': map,
|
60
|
+
'filter': filter,
|
61
|
+
'sum': sum,
|
62
|
+
'min': min,
|
63
|
+
'max': max,
|
64
|
+
'abs': abs,
|
65
|
+
'round': round,
|
66
|
+
'sorted': sorted,
|
67
|
+
'reversed': reversed,
|
68
|
+
'any': any,
|
69
|
+
'all': all,
|
70
|
+
# Type constructors
|
71
|
+
'int': int,
|
72
|
+
'float': float,
|
73
|
+
'str': str,
|
74
|
+
'bool': bool,
|
75
|
+
'list': list,
|
76
|
+
'tuple': tuple,
|
77
|
+
'dict': dict,
|
78
|
+
'set': set,
|
79
|
+
# Math functions
|
80
|
+
'pow': pow,
|
81
|
+
'divmod': divmod,
|
82
|
+
# Exceptions
|
83
|
+
'Exception': Exception,
|
84
|
+
'ValueError': ValueError,
|
85
|
+
'TypeError': TypeError,
|
86
|
+
'KeyError': KeyError,
|
87
|
+
'IndexError': IndexError,
|
88
|
+
'RuntimeError': RuntimeError,
|
89
|
+
# Other safe functions
|
90
|
+
'isinstance': isinstance,
|
91
|
+
'type': type,
|
92
|
+
'hasattr': hasattr,
|
93
|
+
'getattr': getattr,
|
94
|
+
'setattr': setattr,
|
95
|
+
'dir': dir,
|
96
|
+
'help': help,
|
97
|
+
# Disable dangerous functions
|
98
|
+
'__import__': None,
|
99
|
+
'eval': None,
|
100
|
+
'exec': None,
|
101
|
+
'compile': None,
|
102
|
+
'open': None,
|
103
|
+
'input': None,
|
104
|
+
'globals': None,
|
105
|
+
'locals': None,
|
106
|
+
'vars': None,
|
107
|
+
}
|
108
|
+
|
109
|
+
# Set up execution environment with safe builtins
|
52
110
|
if globals_dict is None:
|
53
|
-
globals_dict = {'__builtins__':
|
111
|
+
globals_dict = {'__builtins__': safe_builtins}
|
112
|
+
else:
|
113
|
+
# Override builtins in provided globals
|
114
|
+
globals_dict['__builtins__'] = safe_builtins
|
115
|
+
|
54
116
|
if locals_dict is None:
|
55
117
|
locals_dict = {}
|
56
118
|
|
119
|
+
# Security check: validate code doesn't contain dangerous patterns
|
120
|
+
dangerous_patterns = [
|
121
|
+
'__import__', 'import ', 'from ', 'exec', 'eval',
|
122
|
+
'compile', 'open(', 'file(', 'input(', 'raw_input',
|
123
|
+
'__subclasses__', '__bases__', '__globals__', '__code__',
|
124
|
+
'__class__', 'globals(', 'locals(', 'vars('
|
125
|
+
]
|
126
|
+
|
127
|
+
code_lower = code.lower()
|
128
|
+
for pattern in dangerous_patterns:
|
129
|
+
if pattern.lower() in code_lower:
|
130
|
+
return {
|
131
|
+
'result': None,
|
132
|
+
'stdout': '',
|
133
|
+
'stderr': f'Security Error: Code contains restricted pattern: {pattern}',
|
134
|
+
'success': False
|
135
|
+
}
|
136
|
+
|
57
137
|
# Capture output
|
58
138
|
stdout_buffer = io.StringIO()
|
59
139
|
stderr_buffer = io.StringIO()
|
60
140
|
|
61
141
|
try:
|
62
|
-
# Compile code
|
142
|
+
# Compile code with restricted mode
|
63
143
|
compiled_code = compile(code, '<string>', 'exec')
|
64
144
|
|
65
145
|
# Execute with output capture
|
@@ -12,6 +12,8 @@ import shlex
|
|
12
12
|
import logging
|
13
13
|
import os
|
14
14
|
import time
|
15
|
+
import platform
|
16
|
+
import psutil
|
15
17
|
from typing import Dict, List, Optional, Union
|
16
18
|
from ..approval import require_approval
|
17
19
|
|
@@ -38,7 +40,6 @@ class ShellTools:
|
|
38
40
|
command: str,
|
39
41
|
cwd: Optional[str] = None,
|
40
42
|
timeout: int = 30,
|
41
|
-
shell: bool = False,
|
42
43
|
env: Optional[Dict[str, str]] = None,
|
43
44
|
max_output_size: int = 10000
|
44
45
|
) -> Dict[str, Union[str, int, bool]]:
|
@@ -48,7 +49,6 @@ class ShellTools:
|
|
48
49
|
command: Command to execute
|
49
50
|
cwd: Working directory
|
50
51
|
timeout: Maximum execution time in seconds
|
51
|
-
shell: Whether to run command in shell
|
52
52
|
env: Environment variables
|
53
53
|
max_output_size: Maximum output size in bytes
|
54
54
|
|
@@ -56,8 +56,12 @@ class ShellTools:
|
|
56
56
|
Dictionary with execution results
|
57
57
|
"""
|
58
58
|
try:
|
59
|
-
#
|
60
|
-
|
59
|
+
# Always split command for safety (no shell execution)
|
60
|
+
# Use shlex.split with appropriate posix flag
|
61
|
+
if platform.system() == 'Windows':
|
62
|
+
# Use shlex with posix=False for Windows to handle quotes properly
|
63
|
+
command = shlex.split(command, posix=False)
|
64
|
+
else:
|
61
65
|
command = shlex.split(command)
|
62
66
|
|
63
67
|
# Set up process environment
|
@@ -72,7 +76,7 @@ class ShellTools:
|
|
72
76
|
stdout=subprocess.PIPE,
|
73
77
|
stderr=subprocess.PIPE,
|
74
78
|
cwd=cwd,
|
75
|
-
shell=shell
|
79
|
+
shell=False, # Always use shell=False for security
|
76
80
|
env=process_env,
|
77
81
|
text=True
|
78
82
|
)
|
@@ -201,7 +205,9 @@ class ShellTools:
|
|
201
205
|
try:
|
202
206
|
cpu_percent = psutil.cpu_percent(interval=1)
|
203
207
|
memory = psutil.virtual_memory()
|
204
|
-
|
208
|
+
# Use appropriate root path for the OS
|
209
|
+
root_path = os.path.abspath(os.sep)
|
210
|
+
disk = psutil.disk_usage(root_path)
|
205
211
|
|
206
212
|
return {
|
207
213
|
'cpu': {
|
@@ -223,7 +229,7 @@ class ShellTools:
|
|
223
229
|
'percent': disk.percent
|
224
230
|
},
|
225
231
|
'boot_time': psutil.boot_time(),
|
226
|
-
'platform':
|
232
|
+
'platform': platform.system()
|
227
233
|
}
|
228
234
|
except Exception as e:
|
229
235
|
error_msg = f"Error getting system info: {str(e)}"
|
@@ -246,7 +252,11 @@ if __name__ == "__main__":
|
|
246
252
|
# 1. Execute command
|
247
253
|
print("1. Command Execution")
|
248
254
|
print("------------------------------")
|
249
|
-
|
255
|
+
# Cross-platform directory listing
|
256
|
+
if platform.system() == 'Windows':
|
257
|
+
result = execute_command("dir")
|
258
|
+
else:
|
259
|
+
result = execute_command("ls -la")
|
250
260
|
print(f"Success: {result['success']}")
|
251
261
|
print(f"Output:\n{result['stdout']}")
|
252
262
|
if result['stderr']:
|
@@ -27,6 +27,57 @@ class SpiderTools:
|
|
27
27
|
"""Initialize SpiderTools and check for required packages."""
|
28
28
|
self._session = None
|
29
29
|
|
30
|
+
def _validate_url(self, url: str) -> bool:
|
31
|
+
"""
|
32
|
+
Validate URL to prevent SSRF attacks.
|
33
|
+
|
34
|
+
Args:
|
35
|
+
url: URL to validate
|
36
|
+
|
37
|
+
Returns:
|
38
|
+
bool: True if URL is safe, False otherwise
|
39
|
+
"""
|
40
|
+
try:
|
41
|
+
parsed = urlparse(url)
|
42
|
+
|
43
|
+
# Only allow http/https protocols
|
44
|
+
if parsed.scheme not in ['http', 'https']:
|
45
|
+
return False
|
46
|
+
|
47
|
+
# Reject URLs with no hostname
|
48
|
+
if not parsed.hostname:
|
49
|
+
return False
|
50
|
+
|
51
|
+
# Reject local/internal addresses
|
52
|
+
hostname = parsed.hostname.lower()
|
53
|
+
|
54
|
+
# Block localhost and loopback
|
55
|
+
if hostname in ['localhost', '127.0.0.1', '0.0.0.0', '::1']:
|
56
|
+
return False
|
57
|
+
|
58
|
+
# Block private IP ranges
|
59
|
+
import ipaddress
|
60
|
+
try:
|
61
|
+
ip = ipaddress.ip_address(hostname)
|
62
|
+
if ip.is_private or ip.is_reserved or ip.is_loopback or ip.is_link_local:
|
63
|
+
return False
|
64
|
+
except ValueError:
|
65
|
+
# Not an IP address, continue with domain validation
|
66
|
+
pass
|
67
|
+
|
68
|
+
# Block common internal domains
|
69
|
+
if any(hostname.endswith(domain) for domain in ['.local', '.internal', '.localdomain']):
|
70
|
+
return False
|
71
|
+
|
72
|
+
# Block metadata service endpoints
|
73
|
+
if hostname in ['169.254.169.254', 'metadata.google.internal']:
|
74
|
+
return False
|
75
|
+
|
76
|
+
return True
|
77
|
+
|
78
|
+
except Exception:
|
79
|
+
return False
|
80
|
+
|
30
81
|
def _get_session(self):
|
31
82
|
"""Get or create requests session with common headers."""
|
32
83
|
if util.find_spec('requests') is None:
|
@@ -70,6 +121,10 @@ class SpiderTools:
|
|
70
121
|
Dict: Scraped content or error dict
|
71
122
|
"""
|
72
123
|
try:
|
124
|
+
# Validate URL to prevent SSRF
|
125
|
+
if not self._validate_url(url):
|
126
|
+
return {"error": f"Invalid or potentially dangerous URL: {url}"}
|
127
|
+
|
73
128
|
session = self._get_session()
|
74
129
|
if session is None:
|
75
130
|
return {"error": "requests package not available"}
|
@@ -1,9 +1,10 @@
|
|
1
|
-
praisonaiagents/__init__.py,sha256=
|
1
|
+
praisonaiagents/__init__.py,sha256=TezvgadS1p5FGnIRAUVOB_6Jzb3Of7ZtzjtyeCqRsmM,3017
|
2
2
|
praisonaiagents/approval.py,sha256=UJ4OhfihpFGR5CAaMphqpSvqdZCHi5w2MGw1MByZ1FQ,9813
|
3
3
|
praisonaiagents/main.py,sha256=_-XE7_Y7ChvtLQMivfNFrrnAhv4wSSDhH9WJMWlkS0w,16315
|
4
4
|
praisonaiagents/session.py,sha256=d-CZPYikOHb0q-H9f_IWKJsypnQfz1YKeLLkyxs6oDo,15532
|
5
|
-
praisonaiagents/agent/__init__.py,sha256=
|
6
|
-
praisonaiagents/agent/agent.py,sha256=
|
5
|
+
praisonaiagents/agent/__init__.py,sha256=IhIDtAkfJ99cxbttwou52coih_AejS2-jpazsX6LbDY,350
|
6
|
+
praisonaiagents/agent/agent.py,sha256=20w8H2Fqu8oxX6pbvdEx2VBX6G-U7_lsdjRNI89SwTg,113894
|
7
|
+
praisonaiagents/agent/handoff.py,sha256=Saq0chqfvC6Zf5UbXvmctybbehqnotrXn72JsS-76Q0,13099
|
7
8
|
praisonaiagents/agent/image_agent.py,sha256=-5MXG594HVwSpFMcidt16YBp7udtik-Cp7eXlzLE1fY,8696
|
8
9
|
praisonaiagents/agents/__init__.py,sha256=_1d6Pqyk9EoBSo7E68sKyd1jDRlN1vxvVIRpoMc0Jcw,168
|
9
10
|
praisonaiagents/agents/agents.py,sha256=C_yDdJB4XUuwKA9DrysAtAj3zSYT0IKtfCT4Pxo0oyI,63309
|
@@ -15,12 +16,12 @@ praisonaiagents/knowledge/__init__.py,sha256=xL1Eh-a3xsHyIcU4foOWF-JdWYIYBALJH9b
|
|
15
16
|
praisonaiagents/knowledge/chunking.py,sha256=G6wyHa7_8V0_7VpnrrUXbEmUmptlT16ISJYaxmkSgmU,7678
|
16
17
|
praisonaiagents/knowledge/knowledge.py,sha256=OKPar-XGyAp1ndmbOOdCgqFnTCqpOThYVSIZRxZyP58,15683
|
17
18
|
praisonaiagents/llm/__init__.py,sha256=bSywIHBHH0YUf4hSx-FmFXkRv2g1Rlhuk-gjoImE8j8,925
|
18
|
-
praisonaiagents/llm/llm.py,sha256=
|
19
|
+
praisonaiagents/llm/llm.py,sha256=e6lER7PVJsmY7ytzTG-PoJgriRjNjUP1_edaecxRLB4,113777
|
19
20
|
praisonaiagents/mcp/__init__.py,sha256=ibbqe3_7XB7VrIcUcetkZiUZS1fTVvyMy_AqCSFG8qc,240
|
20
|
-
praisonaiagents/mcp/mcp.py,sha256
|
21
|
+
praisonaiagents/mcp/mcp.py,sha256=-fFx4MHffnN2woLnnV7Pzx3-1SFkn2j8Gp5F5ZIwKJ0,19698
|
21
22
|
praisonaiagents/mcp/mcp_sse.py,sha256=z8TMFhW9xuLQ7QnpOa3n1-nSHt0-Bf27qso0u4qxYSY,8357
|
22
23
|
praisonaiagents/memory/__init__.py,sha256=aEFdhgtTqDdMhc_JCWM-f4XI9cZIj7Wz5g_MUa-0amg,397
|
23
|
-
praisonaiagents/memory/memory.py,sha256=
|
24
|
+
praisonaiagents/memory/memory.py,sha256=D5BmQTktv6VOJ49yW2m1MjjCJ5UDSX1Qo46_443ymKo,44276
|
24
25
|
praisonaiagents/process/__init__.py,sha256=lkYbL7Hn5a0ldvJtkdH23vfIIZLIcanK-65C0MwaorY,52
|
25
26
|
praisonaiagents/process/process.py,sha256=gxhMXG3s4CzaREyuwE5zxCMx2Wp_b_Wd53tDfkj8Qk8,66567
|
26
27
|
praisonaiagents/task/__init__.py,sha256=VL5hXVmyGjINb34AalxpBMl-YW9m5EDcRkMTKkSSl7c,80
|
@@ -33,17 +34,17 @@ praisonaiagents/tools/__init__.py,sha256=Rrgi7_3-yLHpfBB81WUi0-wD_wb_BsukwHVdjDY
|
|
33
34
|
praisonaiagents/tools/arxiv_tools.py,sha256=1stb31zTjLTon4jCnpZG5de9rKc9QWgC0leLegvPXWo,10528
|
34
35
|
praisonaiagents/tools/calculator_tools.py,sha256=S1xPT74Geurvjm52QMMIG29zDXVEWJmM6nmyY7yF298,9571
|
35
36
|
praisonaiagents/tools/csv_tools.py,sha256=4Yr0QYwBXt-1BDXGLalB2eSsFR2mB5rH3KdHmRBQY6E,10036
|
36
|
-
praisonaiagents/tools/duckdb_tools.py,sha256=
|
37
|
+
praisonaiagents/tools/duckdb_tools.py,sha256=OxVCwHoeZLed04Qjwj-GWwFaZ_03IlTUfFlU0H8xW-k,10421
|
37
38
|
praisonaiagents/tools/duckduckgo_tools.py,sha256=ynlB5ZyWfHYjUq0JZXH12TganqTihgD-2IyRgs32y84,1657
|
38
39
|
praisonaiagents/tools/excel_tools.py,sha256=e2HqcwnyBueOyss0xEKxff3zB4w4sNWCOMXvZfbDYlE,11309
|
39
|
-
praisonaiagents/tools/file_tools.py,sha256
|
40
|
+
praisonaiagents/tools/file_tools.py,sha256=N0fjTxxi89UupAvtEUwXjPrBvbppf8bwaNLfnjZ05q4,10824
|
40
41
|
praisonaiagents/tools/json_tools.py,sha256=ApUYNuQ1qnbmYNCxSlx6Tth_H1yo8mhWtZ7Rr2WS6C4,16507
|
41
42
|
praisonaiagents/tools/newspaper_tools.py,sha256=NyhojNPeyULBGcAWGOT1X70qVkh3FgZrpH-S7PEmrwI,12667
|
42
43
|
praisonaiagents/tools/pandas_tools.py,sha256=yzCeY4jetKrFIRA15Tr5OQ5d94T8DaSpzglx2UiWfPs,11092
|
43
|
-
praisonaiagents/tools/python_tools.py,sha256=
|
44
|
+
praisonaiagents/tools/python_tools.py,sha256=4dWJddySR0snCEcQudemg5qvbuNrUYxO-jXnzuWixqM,16461
|
44
45
|
praisonaiagents/tools/searxng_tools.py,sha256=LzxFenzGlSBxnckEPwtEZYemAkU8FUflbFbHf5IZE7o,3159
|
45
|
-
praisonaiagents/tools/shell_tools.py,sha256=
|
46
|
-
praisonaiagents/tools/spider_tools.py,sha256=
|
46
|
+
praisonaiagents/tools/shell_tools.py,sha256=zTdp2B0-9mfnHBJuAErEIh8xtMrP-95mdBtR1uuGLhI,9916
|
47
|
+
praisonaiagents/tools/spider_tools.py,sha256=VCn-D-mbD4uuOnEaknRR9QVJP3dsUJgbfUDIO44N56E,16964
|
47
48
|
praisonaiagents/tools/test.py,sha256=UHOTNrnMo0_H6I2g48re1WNZkrR7f6z25UnlWxiOSbM,1600
|
48
49
|
praisonaiagents/tools/tools.py,sha256=TK5njOmDSpMlyBnbeBzNSlnzXWlnNaTpVqkFPhkMArg,265
|
49
50
|
praisonaiagents/tools/wikipedia_tools.py,sha256=pGko-f33wqXgxJTv8db7TbizY5XnzBQRkNdq_GsplvI,9465
|
@@ -51,7 +52,7 @@ praisonaiagents/tools/xml_tools.py,sha256=iYTMBEk5l3L3ryQ1fkUnNVYK-Nnua2Kx2S0dxN
|
|
51
52
|
praisonaiagents/tools/yaml_tools.py,sha256=uogAZrhXV9O7xvspAtcTfpKSQYL2nlOTvCQXN94-G9A,14215
|
52
53
|
praisonaiagents/tools/yfinance_tools.py,sha256=s2PBj_1v7oQnOobo2fDbQBACEHl61ftG4beG6Z979ZE,8529
|
53
54
|
praisonaiagents/tools/train/data/generatecot.py,sha256=H6bNh-E2hqL5MW6kX3hqZ05g9ETKN2-kudSjiuU_SD8,19403
|
54
|
-
praisonaiagents-0.0.
|
55
|
-
praisonaiagents-0.0.
|
56
|
-
praisonaiagents-0.0.
|
57
|
-
praisonaiagents-0.0.
|
55
|
+
praisonaiagents-0.0.110.dist-info/METADATA,sha256=YvEuh5oBB5MkA7fXyYwD6fCJxMqOcI5L34pJ7lQvm8M,1669
|
56
|
+
praisonaiagents-0.0.110.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
57
|
+
praisonaiagents-0.0.110.dist-info/top_level.txt,sha256=_HsRddrJ23iDx5TTqVUVvXG2HeHBL5voshncAMDGjtA,16
|
58
|
+
praisonaiagents-0.0.110.dist-info/RECORD,,
|
File without changes
|
File without changes
|