Skip to content

Terminal refac #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ac26c6d
Add Terminal and DockerTerminal classes
matheper Nov 15, 2024
513dffd
docker requirement
matheper Nov 15, 2024
3a4beff
terminal fixes
matheper Nov 18, 2024
41cb54b
cleaner output from terminal
matheper Nov 19, 2024
41fb649
integrate terminal into PDBTool and RepoEnv
matheper Nov 19, 2024
a6fb19e
merge main into terminal-refac
matheper Nov 19, 2024
3cc12f5
fix circular import
matheper Nov 19, 2024
eba3ddc
merged main into terminal-refac
matheper Nov 20, 2024
2cbe38b
running docker with uid and gid that matches host
matheper Nov 22, 2024
4c5b97c
Timeout read_terminal if no changes to output
matheper Nov 22, 2024
71c9075
pr comments
matheper Nov 22, 2024
93621de
remove working_dir from terminal run. use tempfile.TemporaryDirectory
matheper Nov 22, 2024
5f42d20
Include os env vars to local terminal by default
matheper Nov 22, 2024
55306ca
Patch base image directly from BytesIO
matheper Nov 22, 2024
8d50088
Terminal clone with class
matheper Nov 22, 2024
01f7b74
lazy terminal initialization
matheper Nov 25, 2024
070bd03
updating volumes while setting working_dir
matheper Nov 25, 2024
2f14336
remove previous working dir from volumes
matheper Nov 25, 2024
511d327
removed mutable default arguments
matheper Nov 25, 2024
f8102e4
aider use docker terminal
matheper Nov 25, 2024
01f2e80
merge main into terminal-refac
matheper Nov 25, 2024
2f51523
run_interactive always string
matheper Nov 25, 2024
fd2f0be
fix tests and entrypoint list
matheper Nov 25, 2024
e01936e
fix test_env tests
matheper Nov 25, 2024
63c1b46
check output using list
matheper Nov 26, 2024
ac46608
Fix docker UID and GID patch logic
matheper Nov 26, 2024
92a6a06
let docker name container, then rename it
matheper Nov 26, 2024
f664aba
Apply suggestions from code review
matheper Nov 26, 2024
cc00f43
Apply suggestions from code review
matheper Nov 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ Froggy is an interactive debugging system for Python. This LLM-based agent can i
conda activate froggy
pip install -e .

To install the development dependencies:

pip install -e '.[dev]'

### Set your API information in llm.cfg
First, make a copy of the template,

Expand Down
9 changes: 5 additions & 4 deletions froggy/envs/aider.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ def __init__(self, **kwargs):
super().__init__(**kwargs)
self.load_dataset()

def reset(self, *, seed=None, options={}):
def reset(self, *, seed=None, options: dict = None):
options = options or {}
self.current_sample = self.dataset[options["task_name"]]
directory = self.current_sample["base_directory"]
entrypoint = self.current_sample["entry_point"]
Expand Down Expand Up @@ -86,7 +87,7 @@ def load_dataset(self):
"instructions": instructions,
"filename": task_name + ".py",
}

def make_froggyignore(self, directory: str, include_gitignore: bool = True):
froggyignore_contents = "\n".join(
[
Expand All @@ -110,10 +111,10 @@ def make_froggyignore(self, directory: str, include_gitignore: bool = True):
gitignore_content = f.read()
froggyignore_contents += "\n"
froggyignore_contents += gitignore_content

with open(directory / ".froggyignore", "w") as f:
f.write(froggyignore_contents)




55 changes: 23 additions & 32 deletions froggy/envs/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import numpy as np
from termcolor import colored

from froggy.terminal import Terminal
from froggy.tools.patchers import CodePatcher
from froggy.tools.pdb import PDBTool
from froggy.utils import _walk, make_is_readonly, show_line_number
Expand Down Expand Up @@ -59,13 +60,14 @@ class RepoEnv(TooledEnv):

def __init__(
self,
path: Optional[str] = None,
path: str | None = None,
entrypoint: str = "python -m pytest -sv .",
readonly_patterns: list[str] = [],
readonly_patterns: list[str] | None = None,
run_on_rewrite: bool = True,
run_timeout: Optional[int] = None,
dir_tree_depth: Optional[int] = None,
run_timeout: int | None = None,
dir_tree_depth: int | None = None,
auto_view_change: bool = True,
terminal: Terminal | None = None,
):
""" """
super().__init__()
Expand All @@ -75,6 +77,7 @@ def __init__(
self.run_timeout = run_timeout
self.dir_tree_depth = dir_tree_depth
self.auto_view_change = auto_view_change
self.terminal = terminal or Terminal()
self.setup_workspace(path, entrypoint, readonly_patterns)
self.last_run_obs = None
self.score = 0
Expand All @@ -84,9 +87,10 @@ def __init__(
def setup_workspace(
self,
path: str,
entrypoint: Optional[str] = None,
readonly_patterns: list[str] = [],
entrypoint: str,
readonly_patterns: list[str] = None,
):
readonly_patterns = readonly_patterns or []
if self.path:
self.cleanup_workspace()

Expand Down Expand Up @@ -122,11 +126,11 @@ def setup_workspace(
self.current_file = None
self.current_file_content = None
self.current_breakpoints_state = {}
if not hasattr(
self, "entrypoint"
): # TODO: entrypoint is currently an optional argument,
self.entrypoint = entrypoint.split()
assert self.entrypoint[0] == "python", "Only support python entrypoint for now."
assert entrypoint.split()[0] == "python", "Only support python entrypoint for now."
self.entrypoint = entrypoint

# Set up the terminal working dir
self.terminal.working_dir = str(self.working_dir)

def cleanup_workspace(self):
self.tempdir.cleanup()
Expand Down Expand Up @@ -162,7 +166,8 @@ def restore(self, *filepaths):

shutil.copy2(self.path / filepath, self.working_dir / filepath)

def reset(self, *, seed=None, options={}):
def reset(self, *, seed=None, options: dict = None):
options = options or {}
self.current_file = None
self.current_file_content = None
self.current_breakpoints_state = {}
Expand All @@ -174,7 +179,7 @@ def reset(self, *, seed=None, options={}):

self.obs = ""
if self.has_tool("pdb"):
self.get_tool("pdb").start_pseudo_terminal()
self.get_tool("pdb").start_pdb(terminal=self.terminal.clone())
self.dbg_obs = self.get_tool("pdb").pdb_obs
self.obs += "Debugging terminal started:\n" f"{self.dbg_obs}\n"

Expand All @@ -200,23 +205,10 @@ def reset(self, *, seed=None, options={}):
return self.obs, self.infos

def run(self):
process = subprocess.Popen(
self.entrypoint,
env=dict(os.environ, NO_COLOR="1"),
cwd=self.working_dir,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
success, output = self.terminal.run(
[self.entrypoint], timeout=self.run_timeout
)
try:
stdout, stderr = process.communicate(timeout=self.run_timeout)
success = process.returncode == 0
except subprocess.TimeoutExpired:
process.kill()
stdout, stderr = "", "Timeout expired."
success = False

self.last_run_obs = stdout + stderr
self.last_run_obs = output
self.score = int(success)
self.done = success

Expand Down Expand Up @@ -317,9 +309,8 @@ def step(self, action: str):
self.obs += "\nNew code has been run."
self.run()
if self.has_tool("pdb"):
# Restart the pseudo terminal to take into account recent changes.
self.get_tool("pdb").close_pseudo_terminal()
self.get_tool("pdb").start_pseudo_terminal()
# Restart pdb to take into account recent changes.
self.get_tool("pdb").restart_pdb()
self.dbg_obs = self.get_tool("pdb").pdb_obs
self.obs += (
"\nDebugging terminal started:\n" f"{self.dbg_obs}\n"
Expand Down
3 changes: 2 additions & 1 deletion froggy/envs/swe_bench.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ def load_dataset(self):
self.ds = load_hf_dataset(self.HF_SWE_BENCH_VERIFIED)["test"]
self.dataset = {row["instance_id"]: row for row in self.ds.sort("instance_id")}

def reset(self, *, seed=None, options={}):
def reset(self, *, seed=None, options: dict = None):
options = options or {}
assert "task_name" in options, "task_name must be provided in options"
assert (
options["task_name"] in self.dataset
Expand Down
3 changes: 2 additions & 1 deletion froggy/envs/terminal_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ def __init__(self, bug_free_code_path, buggy_code_path, **kwargs):
self.tempdir = tempfile.TemporaryDirectory(prefix="TerminalSimulatorEnv-")
self.tempdir_name = self.tempdir.name

def reset(self, *, seed=None, options={}):
def reset(self, *, seed=None, options: dict = None):
options = options or {}
self.tempdir.cleanup()
self.current_sample = self.dataset[options["task_name"]]
shutil.copytree(self.bug_free_code_path, self.tempdir_name, dirs_exist_ok=True)
Expand Down
Loading