mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
55 lines
1.8 KiB
Python
55 lines
1.8 KiB
Python
import asyncio
|
|
import os
|
|
|
|
from openhands.runtime.base import CommandResult
|
|
|
|
|
|
class AsyncBashSession:
|
|
@staticmethod
|
|
async def execute(command: str, work_dir: str) -> CommandResult:
|
|
"""Execute a command in the bash session asynchronously."""
|
|
work_dir = os.path.abspath(work_dir)
|
|
|
|
if not os.path.exists(work_dir):
|
|
raise ValueError(f'Work directory {work_dir} does not exist.')
|
|
|
|
command = command.strip()
|
|
if not command:
|
|
return CommandResult(content='', exit_code=0)
|
|
|
|
try:
|
|
process = await asyncio.subprocess.create_subprocess_shell(
|
|
command,
|
|
stdout=asyncio.subprocess.PIPE,
|
|
stderr=asyncio.subprocess.PIPE,
|
|
cwd=work_dir,
|
|
)
|
|
|
|
try:
|
|
stdout, stderr = await asyncio.wait_for(
|
|
process.communicate(), timeout=30
|
|
)
|
|
output = stdout.decode('utf-8')
|
|
|
|
if stderr:
|
|
output = stderr.decode('utf-8')
|
|
print(f'!##! Error running command: {stderr.decode("utf-8")}')
|
|
|
|
return CommandResult(content=output, exit_code=process.returncode or 0)
|
|
|
|
except asyncio.TimeoutError:
|
|
process.terminate()
|
|
|
|
# Allow a brief moment for cleanup
|
|
try:
|
|
await asyncio.wait_for(process.wait(), timeout=1.0)
|
|
except asyncio.TimeoutError:
|
|
process.kill() # Force kill if it doesn't terminate cleanly
|
|
|
|
return CommandResult(content='Command timed out.', exit_code=-1)
|
|
|
|
except Exception as e:
|
|
return CommandResult(
|
|
content=f'Error running command: {str(e)}', exit_code=-1
|
|
)
|