-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbash_tool.py
89 lines (78 loc) · 3.81 KB
/
bash_tool.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import os
import subprocess
import datetime
import pexpect
import sys
# Get the current minute
current_minute = datetime.datetime.now().strftime("%Y%m%d%H%M")
# Create the directory path based on the current minute
DEFAULT_DIRECTORY = f"/tmp/ai2bash/playground/{current_minute}/"
MAX_OUTPUT_LENGTH = 10000000
env_vars = os.environ.copy()
class BashTool:
"""A class to encapsulate the functionality of running bash commands."""
def __init__(self, directory=DEFAULT_DIRECTORY):
"""Initialize BashTool with the given directory.
Args:
directory (str): The directory to run bash commands in.
"""
self.directory = directory
if not os.path.exists(self.directory):
os.makedirs(self.directory)
def run_command(self, command: str) -> str:
"""Run a bash command and returns its output.
Args:
command (str): The command to run in bash.
Returns:
str: The output of the bash command.
"""
if command.startswith("cat << EOF >"):
# Handle writing to a file using cat << EOF syntax
file_path = command.split(">")[1].strip()
file_content = ""
# Find the position of the EOF marker
eof_pos = command.find("EOF", len("cat << EOF >"))
if eof_pos != -1:
file_content = command[len("cat << EOF >")+len(file_path):eof_pos].strip()
with open(os.path.join(self.directory, file_path), "w") as file:
file.write(file_content)
return f"File '{file_path}' created successfully."
chained_commands = command.split('&&')
output = ''
for cmd in chained_commands:
cmd = cmd.strip()
if cmd.startswith("cd") and not cmd.startswith("cdk"):
new_directory = cmd[3:].strip()
if new_directory == "..":
self.directory = os.path.dirname(self.directory)
else:
potential_directory = os.path.join(self.directory, new_directory)
if os.path.exists(potential_directory) and os.path.isdir(potential_directory):
self.directory = potential_directory
else:
return "Error: Directory not found."
else:
try:
child = pexpect.spawn(cmd, cwd=self.directory, env=env_vars)
child.timeout = 1800 # Set a timeout value of 30 minutes (adjust as needed)
while True:
try:
child.expect('\n')
current_output = child.before.decode('utf-8').strip()
output += current_output + '\n'
print(current_output) # Print the output as it arrives
except pexpect.EOF:
break
except pexpect.TIMEOUT:
dialog = child.before.decode('utf-8').strip()
output += f"System Dialog: {dialog}\n"
response = input(dialog + " ")
child.sendline(response)
child.close()
except pexpect.ExceptionPexpect:
result = subprocess.run(cmd, cwd=self.directory, env=env_vars, shell=True, capture_output=True, text=True)
current_output = result.stdout.strip() if result.returncode == 0 else result.stderr.strip()
output += current_output + '\n'
if len(output) > MAX_OUTPUT_LENGTH:
return f"{output.strip()[:MAX_OUTPUT_LENGTH]} \n ###The rest of the response was truncated due to length####\n"
return output.strip()