import subprocess from tempfile import TemporaryFile from typing import Dict, List from core.tools.base import BaseToolSet, SessionGetter, ToolScope, tool from core.tools.terminal.syscall import SyscallTracer from env import settings from logger import logger class Terminal(BaseToolSet): def __init__(self): self.sessions: Dict[str, List[SyscallTracer]] = {} @tool( name="Terminal", description="Executes commands in a terminal." "If linux errno occurs, we have to solve the problem with the terminal. " "Input must be one valid command. " "Output will be any output from running that command.", scope=ToolScope.SESSION, ) def execute(self, commands: str, get_session: SessionGetter) -> str: session, _ = get_session() try: with TemporaryFile() as fp: process = subprocess.Popen( commands, shell=True, cwd=settings["PLAYGROUND_DIR"], stdout=fp, stderr=fp, ) tracer = SyscallTracer(process.pid) tracer.attach() exitcode, reason = tracer.wait_until_stop_or_exit() logger.debug(f"Stopped terminal execution: {exitcode} {reason}") fp.seek(0) output = fp.read().decode() except Exception as e: output = str(e) logger.debug( f"\nProcessed Terminal, Input Commands: {commands} " f"Output Answer: {output}" ) return output if __name__ == "__main__": import time o = Terminal().execute( "sleep 1; echo 1; sleep 2; echo 2; sleep 3; echo 3; sleep 10;", lambda: ("", None), ) print(o) time.sleep(10) # see if timer has reset