mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
Add SWE-agent tools as sandbox plugins (#1305)
* add initial version of swe-agent plugin; * rename swe cursors * split setup script into two and create two requirements * print SWE-agent command documentation * update swe-agent to default to no custom docs * update dockerfile with dependency from swe-agent * make env setup a separate script for .bashrc source * fix swe-tool plugins; add missing _split_string --------- Co-authored-by: Robert Brennan <accounts@rbren.io>
This commit is contained in:
parent
99829f95fd
commit
a0e8fcb19a
@ -1,4 +1,3 @@
|
||||
from opendevin.parse_commands import parse_command_file
|
||||
|
||||
DEFAULT_COMMANDS_DICT = {
|
||||
'exit': 'Executed when task is complete',
|
||||
@ -29,7 +28,9 @@ COMMAND_USAGE = {
|
||||
DEFAULT_COMMANDS = '\n'.join(
|
||||
[k + ' - ' + v for k, v in DEFAULT_COMMANDS_DICT.items()])
|
||||
|
||||
CUSTOM_DOCS = parse_command_file()
|
||||
# from opendevin.parse_commands import parse_command_file
|
||||
# USE parse_command_file(filepath) to get the custom commands
|
||||
CUSTOM_DOCS = None
|
||||
|
||||
CUSTOM_COMMANDS = f"""Custom bash commands:
|
||||
{CUSTOM_DOCS}
|
||||
|
||||
@ -16,6 +16,11 @@ RUN apt-get update && apt-get install -y \
|
||||
build-essential \
|
||||
openssh-server \
|
||||
sudo \
|
||||
bash \
|
||||
gcc \
|
||||
jq \
|
||||
g++ \
|
||||
make \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN mkdir -p -m0755 /var/run/sshd
|
||||
|
||||
@ -17,7 +17,7 @@ from opendevin.logger import opendevin_logger as logger
|
||||
from opendevin.sandbox.sandbox import Sandbox
|
||||
from opendevin.sandbox.process import Process
|
||||
from opendevin.sandbox.docker.process import DockerProcess
|
||||
from opendevin.sandbox.plugins.jupyter import JupyterRequirement
|
||||
from opendevin.sandbox.plugins import JupyterRequirement, SWEAgentCommandsRequirement
|
||||
from opendevin.schema import ConfigType
|
||||
from opendevin.utils import find_available_tcp_port
|
||||
from opendevin.exceptions import SandboxInvalidBackgroundCommandError
|
||||
@ -444,7 +444,12 @@ if __name__ == '__main__':
|
||||
"Interactive Docker container started. Type 'exit' or use Ctrl+C to exit.")
|
||||
|
||||
# Initialize required plugins
|
||||
ssh_box.init_plugins([JupyterRequirement()])
|
||||
ssh_box.init_plugins([JupyterRequirement(), SWEAgentCommandsRequirement()])
|
||||
logger.info(
|
||||
'--- SWE-AGENT COMMAND DOCUMENTATION ---\n'
|
||||
f'{SWEAgentCommandsRequirement().documentation}\n'
|
||||
'---'
|
||||
)
|
||||
|
||||
bg_cmd = ssh_box.execute_in_background(
|
||||
"while true; do echo 'dot ' && sleep 10; done"
|
||||
|
||||
@ -3,5 +3,6 @@ from .requirement import PluginRequirement
|
||||
|
||||
# Requirements
|
||||
from .jupyter import JupyterRequirement
|
||||
from .swe_agent_commands import SWEAgentCommandsRequirement
|
||||
|
||||
__all__ = ['PluginMixin', 'PluginRequirement', 'JupyterRequirement']
|
||||
__all__ = ['PluginMixin', 'PluginRequirement', 'JupyterRequirement', 'SWEAgentCommandsRequirement']
|
||||
|
||||
64
opendevin/sandbox/plugins/swe_agent_commands/__init__.py
Normal file
64
opendevin/sandbox/plugins/swe_agent_commands/__init__.py
Normal file
@ -0,0 +1,64 @@
|
||||
import os
|
||||
from typing import List
|
||||
from dataclasses import dataclass, field
|
||||
from opendevin.sandbox.plugins.requirement import PluginRequirement
|
||||
from opendevin.sandbox.plugins.swe_agent_commands.parse_commands import parse_command_file
|
||||
|
||||
|
||||
def _resolve_to_cur_dir(filename):
|
||||
return os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
filename
|
||||
)
|
||||
|
||||
|
||||
def check_and_parse_command_file(filepath) -> str:
|
||||
if filepath is None:
|
||||
raise FileNotFoundError(f'File not found: {filepath}')
|
||||
return parse_command_file(filepath)
|
||||
|
||||
|
||||
DEFAULT_SCRIPT_FILEPATHS = [
|
||||
_resolve_to_cur_dir('defaults.sh'),
|
||||
_resolve_to_cur_dir('search.sh'),
|
||||
_resolve_to_cur_dir('edit_linting.sh'),
|
||||
]
|
||||
DEFAULT_DOCUMENTATION = ''.join([
|
||||
check_and_parse_command_file(filepath)
|
||||
for filepath in DEFAULT_SCRIPT_FILEPATHS
|
||||
if filepath is not None
|
||||
])
|
||||
|
||||
|
||||
@dataclass
|
||||
class SWEAgentCommandsRequirement(PluginRequirement):
|
||||
name: str = 'swe_agent_commands'
|
||||
host_src: str = os.path.dirname(os.path.abspath(__file__))
|
||||
sandbox_dest: str = '/opendevin/plugins/swe_agent_commands'
|
||||
bash_script_path: str = 'setup_default.sh'
|
||||
|
||||
scripts_filepaths: List[str | None] = field(default_factory=lambda: DEFAULT_SCRIPT_FILEPATHS)
|
||||
documentation: str = DEFAULT_DOCUMENTATION
|
||||
|
||||
|
||||
CURSOR_SCRIPT_FILEPATHS = [
|
||||
_resolve_to_cur_dir('cursors_defaults.sh'),
|
||||
_resolve_to_cur_dir('cursors_edit_linting.sh'),
|
||||
_resolve_to_cur_dir('search.sh'),
|
||||
]
|
||||
CURSOR_DOCUMENTATION = ''.join([
|
||||
check_and_parse_command_file(filepath)
|
||||
for filepath in CURSOR_SCRIPT_FILEPATHS
|
||||
if filepath is not None
|
||||
])
|
||||
|
||||
|
||||
@dataclass
|
||||
class SWEAgentCursorCommandsRequirement(PluginRequirement):
|
||||
name: str = 'swe_agent_commands'
|
||||
host_src: str = os.path.dirname(os.path.abspath(__file__))
|
||||
sandbox_dest: str = '/opendevin/plugins/swe_agent_commands'
|
||||
bash_script_path: str = 'setup_cursor_mode.sh'
|
||||
|
||||
scripts_filepaths: List[str | None] = field(default_factory=lambda: CURSOR_SCRIPT_FILEPATHS)
|
||||
documentation: str = CURSOR_DOCUMENTATION
|
||||
24
opendevin/sandbox/plugins/swe_agent_commands/_setup_cursor_mode_env.sh
Executable file
24
opendevin/sandbox/plugins/swe_agent_commands/_setup_cursor_mode_env.sh
Executable file
@ -0,0 +1,24 @@
|
||||
# Cursor Mode from SWE-Bench
|
||||
# https://github.com/princeton-nlp/SWE-agent/blob/ca54d5556b9db4f4f2be21f09530ce69a72c0305/config/configs/default_sys-env_cursors_window100-detailed_cmd_format-last_5_history-1_demos.yaml
|
||||
export WINDOW=200;
|
||||
export OVERLAP=2;
|
||||
export CURRENT_LINE=0;
|
||||
export CURRENT_FILE='';
|
||||
export SEARCH_RESULTS=();
|
||||
export SEARCH_FILES=();
|
||||
export SEARCH_INDEX=0;
|
||||
export START_INDEX=0;
|
||||
export END_INDEX=0;
|
||||
export START_CURSOR=0;
|
||||
export END_CURSOR=0;
|
||||
export START_CURSOR_MARK='"<<<<< START CURSOR >>>>>"'; # these have to use double quotes
|
||||
export END_CURSOR_MARK='"<<<<< END CURSOR >>>>>"'; # these have to use double quotes
|
||||
|
||||
state() {
|
||||
local working_dir="$PWD";
|
||||
if [ -z $CURRENT_FILE ]; then
|
||||
echo '{"open_file": "n/a", "working_dir": "'$working_dir'"}';
|
||||
else
|
||||
echo '{"open_file": "'$(realpath $CURRENT_FILE)'", "working_dir": "'$working_dir'"}';
|
||||
fi
|
||||
};
|
||||
18
opendevin/sandbox/plugins/swe_agent_commands/_setup_default_env.sh
Executable file
18
opendevin/sandbox/plugins/swe_agent_commands/_setup_default_env.sh
Executable file
@ -0,0 +1,18 @@
|
||||
# Default Mode from SWE-Bench
|
||||
# https://github.com/princeton-nlp/SWE-agent/blob/ca54d5556b9db4f4f2be21f09530ce69a72c0305/config/configs/default_sys-env_window100-detailed_cmd_format-last_5_history-1_demos.yaml
|
||||
export WINDOW=100;
|
||||
export OVERLAP=2;
|
||||
export CURRENT_LINE=0;
|
||||
export CURRENT_FILE='';
|
||||
export SEARCH_RESULTS=();
|
||||
export SEARCH_FILES=();
|
||||
export SEARCH_INDEX=0;
|
||||
|
||||
state() {
|
||||
local working_dir="$PWD";
|
||||
if [ -z $CURRENT_FILE ]; then
|
||||
echo '{"open_file": "n/a", "working_dir": "'$working_dir'"}';
|
||||
else
|
||||
echo '{"open_file": "'$(realpath $CURRENT_FILE)'", "working_dir": "'$working_dir'"}';
|
||||
fi
|
||||
};
|
||||
17
opendevin/sandbox/plugins/swe_agent_commands/_split_string
Executable file
17
opendevin/sandbox/plugins/swe_agent_commands/_split_string
Executable file
@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
|
||||
|
||||
def print_flake8_output(input_string, show_line_numbers=False):
|
||||
for value in input_string.split('\n'):
|
||||
parts = value.split()
|
||||
if not show_line_numbers:
|
||||
print(f"- {' '.join(parts[1:])}")
|
||||
else:
|
||||
line_nums = ':'.join(parts[0].split(':')[1:])
|
||||
print(f"- {line_nums} {' '.join(parts[1:])}")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
lint_output = sys.argv[1]
|
||||
print_flake8_output(lint_output)
|
||||
306
opendevin/sandbox/plugins/swe_agent_commands/cursors_defaults.sh
Normal file
306
opendevin/sandbox/plugins/swe_agent_commands/cursors_defaults.sh
Normal file
@ -0,0 +1,306 @@
|
||||
_reset_cursors() {
|
||||
export START_CURSOR=1
|
||||
export END_CURSOR=1
|
||||
}
|
||||
|
||||
_constrain_cursors() {
|
||||
# constrain the cursors to be within the bounds of the file [0, total_lines+1]
|
||||
local total_lines=$(awk 'END {print NR}' "$CURRENT_FILE")
|
||||
total_lines=$((total_lines < 1 ? 1 : total_lines)) # if the file is empty, set total_lines to 1
|
||||
local start_line=$((CURRENT_LINE - WINDOW / 2))
|
||||
local end_line=$((CURRENT_LINE + WINDOW / 2))
|
||||
start_line=$((start_line < 1 ? 1 : start_line))
|
||||
end_line=$((end_line > total_lines ? total_lines : end_line))
|
||||
local warning_string=""
|
||||
if [ "$START_CURSOR" -lt "$start_line" ]; then
|
||||
warning_string+="START_CURSOR moved to $start_line\n"
|
||||
START_CURSOR=$start_line
|
||||
elif [ "$START_CURSOR" -gt "$end_line" ]; then
|
||||
START_CURSOR=$end_line
|
||||
warning_string+="START_CURSOR moved to $end_line\n"
|
||||
fi
|
||||
if [ "$END_CURSOR" -lt "$start_line" ]; then
|
||||
warning_string+="END_CURSOR moved to $start_line\n"
|
||||
END_CURSOR=$start_line
|
||||
elif [ "$END_CURSOR" -gt "$end_line" ]; then
|
||||
warning_string+="END_CURSOR moved to $end_line\n"
|
||||
END_CURSOR=$end_line
|
||||
fi
|
||||
export START_CURSOR END_CURSOR
|
||||
echo "$warning_string"
|
||||
echo $START_CURSOR $END_CURSOR
|
||||
}
|
||||
|
||||
_print() {
|
||||
local cursor_warning=$(_constrain_cursors)
|
||||
local cursor_values=$(echo "$cursor_warning" | tail -n 1)
|
||||
cursor_warning=$(echo "$cursor_warning" | head -n -1)
|
||||
export START_CURSOR=$(echo "$cursor_values" | awk '{print $1}')
|
||||
export END_CURSOR=$(echo "$cursor_values" | awk '{print $2}')
|
||||
local total_lines=$(awk 'END {print NR}' $CURRENT_FILE)
|
||||
echo "[File: $(realpath "$CURRENT_FILE") ($total_lines lines total)]"
|
||||
local start_line=$((CURRENT_LINE - WINDOW / 2))
|
||||
local end_line=$((CURRENT_LINE + WINDOW / 2))
|
||||
start_line=$((start_line < 1 ? 1 : start_line))
|
||||
end_line=$((end_line > total_lines ? total_lines : end_line))
|
||||
local lines=()
|
||||
local i=0
|
||||
while IFS= read -r line; do
|
||||
lines[i++]="$line"
|
||||
done < <(awk -v start="$start_line" -v end="$end_line" 'NR>=start && NR<=end {print}' "$CURRENT_FILE")
|
||||
local num_lines=${#lines[@]}
|
||||
if [ $start_line -gt 1 ]; then
|
||||
echo "($((start_line - 1)) more lines above)"
|
||||
fi
|
||||
for ((i=0; i<num_lines+1; i++)) do
|
||||
local line_number=$((start_line + i))
|
||||
if [ $line_number -eq $START_CURSOR ]
|
||||
then
|
||||
echo $START_CURSOR_MARK
|
||||
fi
|
||||
# if i in [0, num_lines-1] then print the line number and the line
|
||||
if [ $i -ge 0 ] && [ $i -lt $num_lines ]
|
||||
then
|
||||
echo "$line_number:${lines[i]}"
|
||||
fi
|
||||
if [ $line_number -eq $END_CURSOR ]
|
||||
then
|
||||
echo $END_CURSOR_MARK
|
||||
fi
|
||||
done
|
||||
lines_below=$(jq -n "$total_lines - $start_line - $num_lines" | jq '[0, .] | max')
|
||||
if [ $lines_below -gt 0 ]; then
|
||||
echo "($lines_below more lines below)"
|
||||
fi
|
||||
if [ -n "$cursor_warning" ]; then
|
||||
echo -e "$cursor_warning"
|
||||
fi
|
||||
}
|
||||
|
||||
_constrain_line() {
|
||||
if [ -z "$CURRENT_FILE" ]
|
||||
then
|
||||
echo "No file open. Use the open command first."
|
||||
return
|
||||
fi
|
||||
local max_line=$(awk 'END {print NR}' $CURRENT_FILE)
|
||||
local half_window=$(jq -n "$WINDOW/2" | jq 'floor')
|
||||
export CURRENT_LINE=$(jq -n "[$CURRENT_LINE, $max_line - $half_window] | min")
|
||||
export CURRENT_LINE=$(jq -n "[$CURRENT_LINE, $half_window] | max")
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: set_cursors <start_line> <end_line>
|
||||
# docstring: sets the start and end cursors to the given line numbers
|
||||
# arguments:
|
||||
# start_line:
|
||||
# type: integer
|
||||
# description: the line number to set the start cursor to
|
||||
# required: true
|
||||
# end_line:
|
||||
# type: integer
|
||||
# description: the line number to set the end cursor to
|
||||
# required: true
|
||||
set_cursors() {
|
||||
if [ -z "$CURRENT_FILE" ]
|
||||
then
|
||||
echo "No file open. Use the open command first."
|
||||
return
|
||||
fi
|
||||
if [ $# -lt 2 ]
|
||||
then
|
||||
echo "Usage: set_cursors <start_line> <end_line>"
|
||||
return
|
||||
fi
|
||||
local start_line=$1
|
||||
local end_line=$2
|
||||
local re='^[0-9]+$'
|
||||
if ! [[ $start_line =~ $re ]]
|
||||
then
|
||||
echo "Usage: set_cursors <start_line> <end_line>"
|
||||
echo "Error: start_line must be a number"
|
||||
return
|
||||
fi
|
||||
if ! [[ $end_line =~ $re ]]
|
||||
then
|
||||
echo "Usage: set_cursors <start_line> <end_line>"
|
||||
echo "Error: end_line must be a number"
|
||||
return
|
||||
fi
|
||||
if [ $start_line -gt $end_line ]
|
||||
then
|
||||
echo "Usage: set_cursors <start_line> <end_line>"
|
||||
echo "Error: start_line must be less than or equal to end_line"
|
||||
return
|
||||
fi
|
||||
export START_CURSOR=$start_line
|
||||
export END_CURSOR=$end_line
|
||||
_print
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: open <path> [<line_number>]
|
||||
# docstring: opens the file at the given path in the editor. If line_number is provided, the window will be centered on that line
|
||||
# arguments:
|
||||
# path:
|
||||
# type: string
|
||||
# description: the path to the file to open
|
||||
# required: true
|
||||
# line_number:
|
||||
# type: integer
|
||||
# description: the line number to move the window to (if not provided, the window will start at the top of the file)
|
||||
# required: false
|
||||
open() {
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Usage: open <file>"
|
||||
return
|
||||
fi
|
||||
# Check if the second argument is provided
|
||||
if [ -n "$2" ]; then
|
||||
# Check if the provided argument is a valid number
|
||||
if ! [[ $2 =~ ^[0-9]+$ ]]; then
|
||||
echo "Usage: open <file> [<line_number>]"
|
||||
echo "Error: <line_number> must be a number"
|
||||
return # Exit if the line number is not valid
|
||||
fi
|
||||
local max_line=$(awk 'END {print NR}' $1)
|
||||
if [ $2 -gt $max_line ]; then
|
||||
echo "Warning: <line_number> ($2) is greater than the number of lines in the file ($max_line)"
|
||||
echo "Warning: Setting <line_number> to $max_line"
|
||||
local line_number=$(jq -n "$max_line") # Set line number to max if greater than max
|
||||
elif [ $2 -lt 1 ]; then
|
||||
echo "Warning: <line_number> ($2) is less than 1"
|
||||
echo "Warning: Setting <line_number> to 1"
|
||||
local line_number=$(jq -n "1") # Set line number to 1 if less than 1
|
||||
else
|
||||
local line_number=$(jq -n "$2") # Set line number if valid
|
||||
fi
|
||||
else
|
||||
local line_number=$(jq -n "$WINDOW/2") # Set default line number if not provided
|
||||
fi
|
||||
|
||||
if [ -f "$1" ]; then
|
||||
export CURRENT_FILE=$(realpath $1)
|
||||
export CURRENT_LINE=$line_number
|
||||
_constrain_line
|
||||
_print
|
||||
else
|
||||
echo "File $1 not found"
|
||||
fi
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: scroll_down
|
||||
# docstring: moves the window down {WINDOW} lines
|
||||
scroll_down() {
|
||||
if [ -z "$CURRENT_FILE" ]
|
||||
then
|
||||
echo "No file open. Use the open command first."
|
||||
return
|
||||
fi
|
||||
export CURRENT_LINE=$(jq -n "$CURRENT_LINE + $WINDOW - $OVERLAP")
|
||||
_constrain_line
|
||||
_print
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: scroll_up
|
||||
# docstring: moves the window up {WINDOW} lines
|
||||
scroll_up() {
|
||||
if [ -z "$CURRENT_FILE" ]
|
||||
then
|
||||
echo "No file open. Use the open command first."
|
||||
return
|
||||
fi
|
||||
export CURRENT_LINE=$(jq -n "$CURRENT_LINE - $WINDOW + $OVERLAP")
|
||||
_constrain_line
|
||||
_print
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: goto <line_number>
|
||||
# docstring: moves the window to show <line_number>
|
||||
# arguments:
|
||||
# line_number:
|
||||
# type: integer
|
||||
# description: the line number to move the window to
|
||||
# required: true
|
||||
goto() {
|
||||
if [ $# -gt 1 ]; then
|
||||
echo "goto allows only one line number at a time."
|
||||
return
|
||||
fi
|
||||
if [ -z "$CURRENT_FILE" ]
|
||||
then
|
||||
echo "No file open. Use the open command first."
|
||||
return
|
||||
fi
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Usage: goto <line>"
|
||||
return
|
||||
fi
|
||||
if ! [[ $1 =~ ^[0-9]+$ ]]
|
||||
then
|
||||
echo "Usage: goto <line>"
|
||||
echo "Error: <line> must be a number"
|
||||
return
|
||||
fi
|
||||
local max_line=$(awk 'END {print NR}' $CURRENT_FILE)
|
||||
if [ $1 -gt $max_line ]
|
||||
then
|
||||
echo "Error: <line> must be less than or equal to $max_line"
|
||||
return
|
||||
fi
|
||||
local OFFSET=$(jq -n "$WINDOW/6" | jq 'floor')
|
||||
export CURRENT_LINE=$(jq -n "[$1 + $WINDOW/2 - $OFFSET, 1] | max | floor")
|
||||
_constrain_line
|
||||
_print
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: create <filename>
|
||||
# docstring: creates and opens a new file with the given name
|
||||
# arguments:
|
||||
# filename:
|
||||
# type: string
|
||||
# description: the name of the file to create
|
||||
# required: true
|
||||
create() {
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: create <filename>"
|
||||
return
|
||||
fi
|
||||
|
||||
# Check if the file already exists
|
||||
if [ -e "$1" ]; then
|
||||
echo "Error: File '$1' already exists."
|
||||
open "$1"
|
||||
return
|
||||
fi
|
||||
|
||||
# Create the file an empty new line
|
||||
printf "\n" > "$1"
|
||||
# Use the existing open command to open the created file
|
||||
open "$1"
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: submit
|
||||
# docstring: submits your current code and terminates the session
|
||||
submit() {
|
||||
cd $ROOT
|
||||
|
||||
# Check if the patch file exists and is non-empty
|
||||
if [ -s "$SWE_CMD_WORK_DIR/test.patch" ]; then
|
||||
# Apply the patch in reverse
|
||||
git apply -R < "$SWE_CMD_WORK_DIR/test.patch"
|
||||
fi
|
||||
|
||||
git add -A
|
||||
git diff --cached > model.patch
|
||||
echo "<<SUBMISSION||"
|
||||
cat model.patch
|
||||
echo "||SUBMISSION>>"
|
||||
}
|
||||
@ -0,0 +1,101 @@
|
||||
# @yaml
|
||||
# signature: |-
|
||||
# edit
|
||||
# <replacement_text>
|
||||
# end_of_edit
|
||||
# docstring: replaces *all* of the text between the START CURSOR and the END CURSOR with the replacement_text. The replacement text is terminated by a line with only end_of_edit on it. All of the <replacement_text> will be entered, so make sure your indentation is formatted properly. To enter text at the beginning of the file, set START CURSOR and END CURSOR to 0. Use set_cursors to move the cursors around. Python files will be checked for syntax errors after the edit.
|
||||
# end_name: end_of_edit
|
||||
# arguments:
|
||||
# replacement_text:
|
||||
# type: string
|
||||
# description: the text to replace the current selection with
|
||||
# required: true
|
||||
edit() {
|
||||
if [ -z "$CURRENT_FILE" ]
|
||||
then
|
||||
echo 'No file open. Use the `open` command first.'
|
||||
return
|
||||
fi
|
||||
local start_line=$((START_CURSOR - 1))
|
||||
start_line=$((start_line < 0 ? 0 : start_line))
|
||||
local end_line=$((END_CURSOR))
|
||||
end_line=$((end_line < 0 ? 0 : end_line))
|
||||
|
||||
local replacement=()
|
||||
while IFS= read -r line
|
||||
do
|
||||
replacement+=("$line")
|
||||
done
|
||||
|
||||
local num_lines=${#replacement[@]}
|
||||
# Create a backup of the current file
|
||||
cp "$CURRENT_FILE" "$SWE_CMD_WORK_DIR/$(basename "$CURRENT_FILE")_backup"
|
||||
# Read the file line by line into an array
|
||||
mapfile -t lines < "$CURRENT_FILE"
|
||||
local new_lines=("${lines[@]:0:$start_line}" "${replacement[@]}" "${lines[@]:$((end_line))}")
|
||||
# Write the new stuff directly back into the original file
|
||||
printf "%s\n" "${new_lines[@]}" >| "$CURRENT_FILE"
|
||||
# Run linter
|
||||
if [[ $CURRENT_FILE == *.py ]]; then
|
||||
lint_output=$(flake8 --isolated --select=F821,F822,F831,E111,E112,E113,E999,E902 "$CURRENT_FILE" 2>&1)
|
||||
else
|
||||
# do nothing
|
||||
lint_output=""
|
||||
fi
|
||||
# if there is no output, then the file is good
|
||||
if [ -z "$lint_output" ]; then
|
||||
_constrain_line
|
||||
# set to START + num_lines - 1, unless num_lines is 0, then set to START
|
||||
export END_CURSOR=$((num_lines == 0 ? START_CURSOR : START_CURSOR + num_lines - 1))
|
||||
export START_CURSOR=$START_CURSOR
|
||||
_print
|
||||
echo "File updated. Please review the changes and make sure they are correct (correct indentation, no duplicate lines, etc). Edit the file again if necessary."
|
||||
else
|
||||
echo "Your proposed edit has introduced new syntax error(s). Please understand the fixes and retry your edit commmand."
|
||||
echo ""
|
||||
echo "ERRORS:"
|
||||
_split_string "$lint_output"
|
||||
echo ""
|
||||
|
||||
# Save original values
|
||||
original_current_line=$CURRENT_LINE
|
||||
original_window=$WINDOW
|
||||
original_end_cursor=$END_CURSOR
|
||||
|
||||
# Update values
|
||||
export CURRENT_LINE=$(( (num_lines / 2) + start_line )) # Set to "center" of edit
|
||||
export WINDOW=$((num_lines + 10)) # Show +/- 5 lines around edit
|
||||
export END_CURSOR=$((num_lines == 0 ? START_CURSOR : START_CURSOR + num_lines - 1))
|
||||
|
||||
echo "This is how your edit would have looked if applied"
|
||||
echo "-------------------------------------------------"
|
||||
_constrain_line
|
||||
_print
|
||||
echo "-------------------------------------------------"
|
||||
echo ""
|
||||
|
||||
# Restoring CURRENT_FILE to original contents.
|
||||
cp "$SWE_CMD_WORK_DIR/$(basename "$CURRENT_FILE")_backup" "$CURRENT_FILE"
|
||||
|
||||
export CURRENT_LINE=$(( ((end_line - start_line) / 2) + start_line )) # Set to "center" of edit
|
||||
export WINDOW=$((end_line - start_line + 10))
|
||||
export END_CURSOR=$original_end_cursor
|
||||
|
||||
echo "This is the original code before your edit"
|
||||
echo "-------------------------------------------------"
|
||||
_constrain_line
|
||||
_print
|
||||
echo "-------------------------------------------------"
|
||||
|
||||
# Restore original values
|
||||
export CURRENT_LINE=$original_current_line
|
||||
export WINDOW=$original_window
|
||||
export END_CURSOR=$original_end_cursor
|
||||
|
||||
echo "Your changes have NOT been applied. Please fix your edit command and try again."
|
||||
echo "You either need to 1) Specify the correct start/end line arguments or 2) Correct your edit code."
|
||||
echo "DO NOT re-run the same failed edit command. Running it again will lead to the same error."
|
||||
fi
|
||||
# Remove backup file
|
||||
rm -f "$SWE_CMD_WORK_DIR/$(basename "$CURRENT_FILE")_backup"
|
||||
}
|
||||
195
opendevin/sandbox/plugins/swe_agent_commands/defaults.sh
Normal file
195
opendevin/sandbox/plugins/swe_agent_commands/defaults.sh
Normal file
@ -0,0 +1,195 @@
|
||||
_print() {
|
||||
local total_lines=$(awk 'END {print NR}' $CURRENT_FILE)
|
||||
echo "[File: $(realpath $CURRENT_FILE) ($total_lines lines total)]"
|
||||
lines_above=$(jq -n "$CURRENT_LINE - $WINDOW/2" | jq '[0, .] | max | floor')
|
||||
lines_below=$(jq -n "$total_lines - $CURRENT_LINE - $WINDOW/2" | jq '[0, .] | max | round')
|
||||
if [ $lines_above -gt 0 ]; then
|
||||
echo "($lines_above more lines above)"
|
||||
fi
|
||||
cat $CURRENT_FILE | grep -n $ | head -n $(jq -n "[$CURRENT_LINE + $WINDOW/2, $WINDOW/2] | max | floor") | tail -n $(jq -n "$WINDOW")
|
||||
if [ $lines_below -gt 0 ]; then
|
||||
echo "($lines_below more lines below)"
|
||||
fi
|
||||
}
|
||||
|
||||
_constrain_line() {
|
||||
if [ -z "$CURRENT_FILE" ]
|
||||
then
|
||||
echo "No file open. Use the open command first."
|
||||
return
|
||||
fi
|
||||
local max_line=$(awk 'END {print NR}' $CURRENT_FILE)
|
||||
local half_window=$(jq -n "$WINDOW/2" | jq 'floor')
|
||||
export CURRENT_LINE=$(jq -n "[$CURRENT_LINE, $max_line - $half_window] | min")
|
||||
export CURRENT_LINE=$(jq -n "[$CURRENT_LINE, $half_window] | max")
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: open <path> [<line_number>]
|
||||
# docstring: opens the file at the given path in the editor. If line_number is provided, the window will be move to include that line
|
||||
# arguments:
|
||||
# path:
|
||||
# type: string
|
||||
# description: the path to the file to open
|
||||
# required: true
|
||||
# line_number:
|
||||
# type: integer
|
||||
# description: the line number to move the window to (if not provided, the window will start at the top of the file)
|
||||
# required: false
|
||||
open() {
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Usage: open <file>"
|
||||
return
|
||||
fi
|
||||
# Check if the second argument is provided
|
||||
if [ -n "$2" ]; then
|
||||
# Check if the provided argument is a valid number
|
||||
if ! [[ $2 =~ ^[0-9]+$ ]]; then
|
||||
echo "Usage: open <file> [<line_number>]"
|
||||
echo "Error: <line_number> must be a number"
|
||||
return # Exit if the line number is not valid
|
||||
fi
|
||||
local max_line=$(awk 'END {print NR}' $1)
|
||||
if [ $2 -gt $max_line ]; then
|
||||
echo "Warning: <line_number> ($2) is greater than the number of lines in the file ($max_line)"
|
||||
echo "Warning: Setting <line_number> to $max_line"
|
||||
local line_number=$(jq -n "$max_line") # Set line number to max if greater than max
|
||||
elif [ $2 -lt 1 ]; then
|
||||
echo "Warning: <line_number> ($2) is less than 1"
|
||||
echo "Warning: Setting <line_number> to 1"
|
||||
local line_number=$(jq -n "1") # Set line number to 1 if less than 1
|
||||
else
|
||||
local OFFSET=$(jq -n "$WINDOW/6" | jq 'floor')
|
||||
local line_number=$(jq -n "[$2 + $WINDOW/2 - $OFFSET, 1] | max | floor")
|
||||
fi
|
||||
else
|
||||
local line_number=$(jq -n "$WINDOW/2") # Set default line number if not provided
|
||||
fi
|
||||
|
||||
if [ -f "$1" ]; then
|
||||
export CURRENT_FILE=$(realpath $1)
|
||||
export CURRENT_LINE=$line_number
|
||||
_constrain_line
|
||||
_print
|
||||
elif [ -d "$1" ]; then
|
||||
echo "Error: $1 is a directory. You can only open files. Use cd or ls to navigate directories."
|
||||
else
|
||||
echo "File $1 not found"
|
||||
fi
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: goto <line_number>
|
||||
# docstring: moves the window to show <line_number>
|
||||
# arguments:
|
||||
# line_number:
|
||||
# type: integer
|
||||
# description: the line number to move the window to
|
||||
# required: true
|
||||
goto() {
|
||||
if [ $# -gt 1 ]; then
|
||||
echo "goto allows only one line number at a time."
|
||||
return
|
||||
fi
|
||||
if [ -z "$CURRENT_FILE" ]
|
||||
then
|
||||
echo "No file open. Use the open command first."
|
||||
return
|
||||
fi
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Usage: goto <line>"
|
||||
return
|
||||
fi
|
||||
if ! [[ $1 =~ ^[0-9]+$ ]]
|
||||
then
|
||||
echo "Usage: goto <line>"
|
||||
echo "Error: <line> must be a number"
|
||||
return
|
||||
fi
|
||||
local max_line=$(awk 'END {print NR}' $CURRENT_FILE)
|
||||
if [ $1 -gt $max_line ]
|
||||
then
|
||||
echo "Error: <line> must be less than or equal to $max_line"
|
||||
return
|
||||
fi
|
||||
local OFFSET=$(jq -n "$WINDOW/6" | jq 'floor')
|
||||
export CURRENT_LINE=$(jq -n "[$1 + $WINDOW/2 - $OFFSET, 1] | max | floor")
|
||||
_constrain_line
|
||||
_print
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: scroll_down
|
||||
# docstring: moves the window down {WINDOW} lines
|
||||
scroll_down() {
|
||||
if [ -z "$CURRENT_FILE" ]
|
||||
then
|
||||
echo "No file open. Use the open command first."
|
||||
return
|
||||
fi
|
||||
export CURRENT_LINE=$(jq -n "$CURRENT_LINE + $WINDOW - $OVERLAP")
|
||||
_constrain_line
|
||||
_print
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: scroll_up
|
||||
# docstring: moves the window down {WINDOW} lines
|
||||
scroll_up() {
|
||||
if [ -z "$CURRENT_FILE" ]
|
||||
then
|
||||
echo "No file open. Use the open command first."
|
||||
return
|
||||
fi
|
||||
export CURRENT_LINE=$(jq -n "$CURRENT_LINE - $WINDOW + $OVERLAP")
|
||||
_constrain_line
|
||||
_print
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: create <filename>
|
||||
# docstring: creates and opens a new file with the given name
|
||||
# arguments:
|
||||
# filename:
|
||||
# type: string
|
||||
# description: the name of the file to create
|
||||
# required: true
|
||||
create() {
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: create <filename>"
|
||||
return
|
||||
fi
|
||||
|
||||
# Check if the file already exists
|
||||
if [ -e "$1" ]; then
|
||||
echo "Error: File '$1' already exists."
|
||||
open "$1"
|
||||
return
|
||||
fi
|
||||
|
||||
# Create the file an empty new line
|
||||
printf "\n" > "$1"
|
||||
# Use the existing open command to open the created file
|
||||
open "$1"
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: submit
|
||||
# docstring: submits your current code and terminates the session
|
||||
submit() {
|
||||
cd $ROOT
|
||||
|
||||
# Check if the patch file exists and is non-empty
|
||||
if [ -s "$SWE_CMD_WORK_DIR/test.patch" ]; then
|
||||
# Apply the patch in reverse
|
||||
git apply -R < "$SWE_CMD_WORK_DIR/test.patch"
|
||||
fi
|
||||
|
||||
git add -A
|
||||
git diff --cached > model.patch
|
||||
echo "<<SUBMISSION||"
|
||||
cat model.patch
|
||||
echo "||SUBMISSION>>"
|
||||
}
|
||||
130
opendevin/sandbox/plugins/swe_agent_commands/edit_linting.sh
Normal file
130
opendevin/sandbox/plugins/swe_agent_commands/edit_linting.sh
Normal file
@ -0,0 +1,130 @@
|
||||
# @yaml
|
||||
# signature: |-
|
||||
# edit <start_line>:<end_line>
|
||||
# <replacement_text>
|
||||
# end_of_edit
|
||||
# docstring: replaces lines <start_line> through <end_line> (inclusive) with the given text in the open file. The replacement text is terminated by a line with only end_of_edit on it. All of the <replacement text> will be entered, so make sure your indentation is formatted properly. Python files will be checked for syntax errors after the edit. If the system detects a syntax error, the edit will not be executed. Simply try to edit the file again, but make sure to read the error message and modify the edit command you issue accordingly. Issuing the same command a second time will just lead to the same error message again.
|
||||
# end_name: end_of_edit
|
||||
# arguments:
|
||||
# start_line:
|
||||
# type: integer
|
||||
# description: the line number to start the edit at
|
||||
# required: true
|
||||
# end_line:
|
||||
# type: integer
|
||||
# description: the line number to end the edit at (inclusive)
|
||||
# required: true
|
||||
# replacement_text:
|
||||
# type: string
|
||||
# description: the text to replace the current selection with
|
||||
# required: true
|
||||
edit() {
|
||||
if [ -z "$CURRENT_FILE" ]
|
||||
then
|
||||
echo 'No file open. Use the `open` command first.'
|
||||
return
|
||||
fi
|
||||
|
||||
local start_line="$(echo $1: | cut -d: -f1)"
|
||||
local end_line="$(echo $1: | cut -d: -f2)"
|
||||
|
||||
if [ -z "$start_line" ] || [ -z "$end_line" ]
|
||||
then
|
||||
echo "Usage: edit <start_line>:<end_line>"
|
||||
return
|
||||
fi
|
||||
|
||||
local re='^[0-9]+$'
|
||||
if ! [[ $start_line =~ $re ]]; then
|
||||
echo "Usage: edit <start_line>:<end_line>"
|
||||
echo "Error: start_line must be a number"
|
||||
return
|
||||
fi
|
||||
if ! [[ $end_line =~ $re ]]; then
|
||||
echo "Usage: edit <start_line>:<end_line>"
|
||||
echo "Error: end_line must be a number"
|
||||
return
|
||||
fi
|
||||
|
||||
# Bash array starts at 0, so let's adjust
|
||||
local start_line=$((start_line - 1))
|
||||
local end_line=$((end_line))
|
||||
|
||||
local line_count=0
|
||||
local replacement=()
|
||||
while IFS= read -r line
|
||||
do
|
||||
replacement+=("$line")
|
||||
((line_count++))
|
||||
done
|
||||
|
||||
# Create a backup of the current file
|
||||
cp "$CURRENT_FILE" "$SWE_CMD_WORK_DIR/$(basename "$CURRENT_FILE")_backup"
|
||||
|
||||
# Read the file line by line into an array
|
||||
mapfile -t lines < "$CURRENT_FILE"
|
||||
local new_lines=("${lines[@]:0:$start_line}" "${replacement[@]}" "${lines[@]:$((end_line))}")
|
||||
# Write the new stuff directly back into the original file
|
||||
printf "%s\n" "${new_lines[@]}" >| "$CURRENT_FILE"
|
||||
|
||||
# Run linter
|
||||
if [[ $CURRENT_FILE == *.py ]]; then
|
||||
lint_output=$(flake8 --isolated --select=F821,F822,F831,E111,E112,E113,E999,E902 "$CURRENT_FILE" 2>&1)
|
||||
else
|
||||
# do nothing
|
||||
lint_output=""
|
||||
fi
|
||||
|
||||
# if there is no output, then the file is good
|
||||
if [ -z "$lint_output" ]; then
|
||||
export CURRENT_LINE=$start_line
|
||||
_constrain_line
|
||||
_print
|
||||
|
||||
echo "File updated. Please review the changes and make sure they are correct (correct indentation, no duplicate lines, etc). Edit the file again if necessary."
|
||||
else
|
||||
echo "Your proposed edit has introduced new syntax error(s). Please understand the fixes and retry your edit commmand."
|
||||
echo ""
|
||||
echo "ERRORS:"
|
||||
_split_string "$lint_output"
|
||||
echo ""
|
||||
|
||||
# Save original values
|
||||
original_current_line=$CURRENT_LINE
|
||||
original_window=$WINDOW
|
||||
|
||||
# Update values
|
||||
export CURRENT_LINE=$(( (line_count / 2) + start_line )) # Set to "center" of edit
|
||||
export WINDOW=$((line_count + 10)) # Show +/- 5 lines around edit
|
||||
|
||||
echo "This is how your edit would have looked if applied"
|
||||
echo "-------------------------------------------------"
|
||||
_constrain_line
|
||||
_print
|
||||
echo "-------------------------------------------------"
|
||||
echo ""
|
||||
|
||||
# Restoring CURRENT_FILE to original contents.
|
||||
cp "$SWE_CMD_WORK_DIR/$(basename "$CURRENT_FILE")_backup" "$CURRENT_FILE"
|
||||
|
||||
export CURRENT_LINE=$(( ((end_line - start_line + 1) / 2) + start_line ))
|
||||
export WINDOW=$((end_line - start_line + 10))
|
||||
|
||||
echo "This is the original code before your edit"
|
||||
echo "-------------------------------------------------"
|
||||
_constrain_line
|
||||
_print
|
||||
echo "-------------------------------------------------"
|
||||
|
||||
# Restore original values
|
||||
export CURRENT_LINE=$original_current_line
|
||||
export WINDOW=$original_window
|
||||
|
||||
echo "Your changes have NOT been applied. Please fix your edit command and try again."
|
||||
echo "You either need to 1) Specify the correct start/end line arguments or 2) Correct your edit code."
|
||||
echo "DO NOT re-run the same failed edit command. Running it again will lead to the same error."
|
||||
fi
|
||||
|
||||
# Remove backup file
|
||||
rm -f "$SWE_CMD_WORK_DIR/$(basename "$CURRENT_FILE")_backup"
|
||||
}
|
||||
@ -1,4 +1,3 @@
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
|
||||
import yaml
|
||||
@ -11,10 +10,8 @@ class Command:
|
||||
signature: str | None = None
|
||||
|
||||
|
||||
def parse_command_file() -> str | None:
|
||||
if not os.path.exists('commands.sh'):
|
||||
return None
|
||||
content = open('commands.sh', 'r').read()
|
||||
def parse_command_file(filepath: str) -> str:
|
||||
content = open(filepath, 'r').read()
|
||||
lines = content.split('\n')
|
||||
commands: list[Command] = []
|
||||
idx = 0
|
||||
@ -50,3 +47,15 @@ def parse_command_file() -> str | None:
|
||||
if cmd.docstring is not None:
|
||||
function_docs += f'{cmd.signature or cmd.name} - {cmd.docstring}\n'
|
||||
return function_docs
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
if len(sys.argv) < 2:
|
||||
print('Usage: python parse_commands.py <file>')
|
||||
sys.exit(1)
|
||||
filepath = sys.argv[1]
|
||||
filepaths = filepath.split(',')
|
||||
for filepath in filepaths:
|
||||
docs = parse_command_file(filepath)
|
||||
print(docs)
|
||||
155
opendevin/sandbox/plugins/swe_agent_commands/search.sh
Normal file
155
opendevin/sandbox/plugins/swe_agent_commands/search.sh
Normal file
@ -0,0 +1,155 @@
|
||||
# @yaml
|
||||
# signature: search_dir <search_term> [<dir>]
|
||||
# docstring: searches for search_term in all files in dir. If dir is not provided, searches in the current directory
|
||||
# arguments:
|
||||
# search_term:
|
||||
# type: string
|
||||
# description: the term to search for
|
||||
# required: true
|
||||
# dir:
|
||||
# type: string
|
||||
# description: the directory to search in (if not provided, searches in the current directory)
|
||||
# required: false
|
||||
search_dir() {
|
||||
if [ $# -eq 1 ]; then
|
||||
local search_term="$1"
|
||||
local dir="./"
|
||||
elif [ $# -eq 2 ]; then
|
||||
local search_term="$1"
|
||||
if [ -d "$2" ]; then
|
||||
local dir="$2"
|
||||
else
|
||||
echo "Directory $2 not found"
|
||||
return
|
||||
fi
|
||||
else
|
||||
echo "Usage: search_dir <search_term> [<dir>]"
|
||||
return
|
||||
fi
|
||||
dir=$(realpath "$dir")
|
||||
local matches=$(find "$dir" -type f ! -path '*/.*' -exec grep -nIH -- "$search_term" {} + | cut -d: -f1 | sort | uniq -c)
|
||||
# if no matches, return
|
||||
if [ -z "$matches" ]; then
|
||||
echo "No matches found for \"$search_term\" in $dir"
|
||||
return
|
||||
fi
|
||||
# Calculate total number of matches
|
||||
local num_matches=$(echo "$matches" | awk '{sum+=$1} END {print sum}')
|
||||
# calculate total number of files matched
|
||||
local num_files=$(echo "$matches" | wc -l | awk '{$1=$1; print $0}')
|
||||
# if num_files is > 100, print an error
|
||||
if [ $num_files -gt 100 ]; then
|
||||
echo "More than $num_files files matched for \"$search_term\" in $dir. Please narrow your search."
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Found $num_matches matches for \"$search_term\" in $dir:"
|
||||
echo "$matches" | awk '{$2=$2; gsub(/^\.+\/+/, "./", $2); print $2 " ("$1" matches)"}'
|
||||
echo "End of matches for \"$search_term\" in $dir"
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: search_file <search_term> [<file>]
|
||||
# docstring: searches for search_term in file. If file is not provided, searches in the current open file
|
||||
# arguments:
|
||||
# search_term:
|
||||
# type: string
|
||||
# description: the term to search for
|
||||
# required: true
|
||||
# file:
|
||||
# type: string
|
||||
# description: the file to search in (if not provided, searches in the current open file)
|
||||
# required: false
|
||||
search_file() {
|
||||
# Check if the first argument is provided
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: search_file <search_term> [<file>]"
|
||||
return
|
||||
fi
|
||||
# Check if the second argument is provided
|
||||
if [ -n "$2" ]; then
|
||||
# Check if the provided argument is a valid file
|
||||
if [ -f "$2" ]; then
|
||||
local file="$2" # Set file if valid
|
||||
else
|
||||
echo "Usage: search_file <search_term> [<file>]"
|
||||
echo "Error: File name $2 not found. Please provide a valid file name."
|
||||
return # Exit if the file is not valid
|
||||
fi
|
||||
else
|
||||
# Check if a file is open
|
||||
if [ -z "$CURRENT_FILE" ]; then
|
||||
echo "No file open. Use the open command first."
|
||||
return # Exit if no file is open
|
||||
fi
|
||||
local file="$CURRENT_FILE" # Set file to the current open file
|
||||
fi
|
||||
local search_term="$1"
|
||||
file=$(realpath "$file")
|
||||
# Use grep to directly get the desired formatted output
|
||||
local matches=$(grep -nH -- "$search_term" "$file")
|
||||
# Check if no matches were found
|
||||
if [ -z "$matches" ]; then
|
||||
echo "No matches found for \"$search_term\" in $file"
|
||||
return
|
||||
fi
|
||||
# Calculate total number of matches
|
||||
local num_matches=$(echo "$matches" | wc -l | awk '{$1=$1; print $0}')
|
||||
|
||||
# calculate total number of lines matched
|
||||
local num_lines=$(echo "$matches" | cut -d: -f1 | sort | uniq | wc -l | awk '{$1=$1; print $0}')
|
||||
# if num_lines is > 100, print an error
|
||||
if [ $num_lines -gt 100 ]; then
|
||||
echo "More than $num_lines lines matched for \"$search_term\" in $file. Please narrow your search."
|
||||
return
|
||||
fi
|
||||
|
||||
# Print the total number of matches and the matches themselves
|
||||
echo "Found $num_matches matches for \"$search_term\" in $file:"
|
||||
echo "$matches" | cut -d: -f1-2 | sort -u -t: -k2,2n | while IFS=: read -r filename line_number; do
|
||||
echo "Line $line_number:$(sed -n "${line_number}p" "$file")"
|
||||
done
|
||||
echo "End of matches for \"$search_term\" in $file"
|
||||
}
|
||||
|
||||
# @yaml
|
||||
# signature: find_file <file_name> [<dir>]
|
||||
# docstring: finds all files with the given name in dir. If dir is not provided, searches in the current directory
|
||||
# arguments:
|
||||
# file_name:
|
||||
# type: string
|
||||
# description: the name of the file to search for
|
||||
# required: true
|
||||
# dir:
|
||||
# type: string
|
||||
# description: the directory to search in (if not provided, searches in the current directory)
|
||||
# required: false
|
||||
find_file() {
|
||||
if [ $# -eq 1 ]; then
|
||||
local file_name="$1"
|
||||
local dir="./"
|
||||
elif [ $# -eq 2 ]; then
|
||||
local file_name="$1"
|
||||
if [ -d "$2" ]; then
|
||||
local dir="$2"
|
||||
else
|
||||
echo "Directory $2 not found"
|
||||
return
|
||||
fi
|
||||
else
|
||||
echo "Usage: find_file <file_name> [<dir>]"
|
||||
return
|
||||
fi
|
||||
|
||||
dir=$(realpath "$dir")
|
||||
local matches=$(find "$dir" -type f -name "$file_name")
|
||||
# if no matches, return
|
||||
if [ -z "$matches" ]; then
|
||||
echo "No matches found for \"$file_name\" in $dir"
|
||||
return
|
||||
fi
|
||||
# Calculate total number of matches
|
||||
local num_matches=$(echo "$matches" | wc -l | awk '{$1=$1; print $0}')
|
||||
echo "Found $num_matches matches for \"$file_name\" in $dir:"
|
||||
echo "$matches" | awk '{print $0}'
|
||||
}
|
||||
18
opendevin/sandbox/plugins/swe_agent_commands/setup_cursor_mode.sh
Executable file
18
opendevin/sandbox/plugins/swe_agent_commands/setup_cursor_mode.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
pip install flake8
|
||||
|
||||
# Cursor Mode from SWE-Bench
|
||||
# https://github.com/princeton-nlp/SWE-agent/blob/ca54d5556b9db4f4f2be21f09530ce69a72c0305/config/configs/default_sys-env_cursors_window100-detailed_cmd_format-last_5_history-1_demos.yaml#L108-L111
|
||||
echo 'source /opendevin/plugins/swe_agent_commands/_setup_cursor_mode_env.sh' >> ~/.bashrc
|
||||
|
||||
# make _split_string (py) available
|
||||
echo 'export PATH=$PATH:/opendevin/plugins/swe_agent_commands' >> ~/.bashrc
|
||||
|
||||
echo 'source /opendevin/plugins/swe_agent_commands/cursors_defaults.sh' >> ~/.bashrc
|
||||
echo 'source /opendevin/plugins/swe_agent_commands/cursors_edit_linting.sh' >> ~/.bashrc
|
||||
echo 'source /opendevin/plugins/swe_agent_commands/search.sh' >> ~/.bashrc
|
||||
|
||||
echo 'export SWE_CMD_WORK_DIR="/opendevin/plugins/swe_agent_commands/workdir"' >> ~/.bashrc
|
||||
sudo mkdir -p /opendevin/plugins/swe_agent_commands/workdir
|
||||
sudo chmod 777 /opendevin/plugins/swe_agent_commands/workdir
|
||||
18
opendevin/sandbox/plugins/swe_agent_commands/setup_default.sh
Executable file
18
opendevin/sandbox/plugins/swe_agent_commands/setup_default.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
pip install flake8
|
||||
|
||||
# Default Mode from SWE-Bench
|
||||
# https://github.com/princeton-nlp/SWE-agent/blob/ca54d5556b9db4f4f2be21f09530ce69a72c0305/config/configs/default_sys-env_window100-detailed_cmd_format-last_5_history-1_demos.yaml#L103-L106
|
||||
echo 'source /opendevin/plugins/swe_agent_commands/_setup_default_env.sh' >> ~/.bashrc
|
||||
|
||||
# make _split_string (py) available
|
||||
echo 'export PATH=$PATH:/opendevin/plugins/swe_agent_commands' >> ~/.bashrc
|
||||
|
||||
echo 'source /opendevin/plugins/swe_agent_commands/defaults.sh' >> ~/.bashrc
|
||||
echo 'source /opendevin/plugins/swe_agent_commands/search.sh' >> ~/.bashrc
|
||||
echo 'source /opendevin/plugins/swe_agent_commands/edit_linting.sh' >> ~/.bashrc
|
||||
|
||||
echo 'export SWE_CMD_WORK_DIR="/opendevin/plugins/swe_agent_commands/workdir"' >> ~/.bashrc
|
||||
sudo mkdir -p /opendevin/plugins/swe_agent_commands/workdir
|
||||
sudo chmod 777 /opendevin/plugins/swe_agent_commands/workdir
|
||||
Loading…
x
Reference in New Issue
Block a user