Skip to content
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

Sweep: If Sweep edits a file to be completely empty, delete it in the pull request #498

Open
wwzeng1 opened this issue Jul 14, 2023 · 1 comment · Fixed by #499
Open
Labels
sweep Assigns Sweep to an issue or pull request.

Comments

@wwzeng1
Copy link
Contributor

wwzeng1 commented Jul 14, 2023

Description

Do this in create_pr

Relevant files

No response

@wwzeng1 wwzeng1 added the sweep Assigns Sweep to an issue or pull request. label Jul 14, 2023
@sweep-nightly
Copy link
Contributor

sweep-nightly bot commented Jul 14, 2023

Here's the PR! #499.

To create this ticket, I used gpt-4. You have 25 gpt-4 tickets left.


Step 1: 🔍 Code Search

I found the following snippets in your repository. I will now analyze these snippets and come up with a plan.

Some code snippets I looked at (click to expand). If some file is missing from here, you can mention the path in the ticket description.

snippets, tree = fetch_file_contents_with_retry()
assert len(snippets) > 0
except Exception as e:
logger.error(traceback.format_exc())
raise e
chat_logger = ChatLogger({
'repo_name': repo_name,
'title': '(Comment) ' + pr_title,
"issue_url": pr.html_url,
"pr_file_path": pr_file_path, # may be None
"pr_line": pr_line, # may be None
"repo_full_name": repo_full_name,
"repo_description": repo_description,
"comment": comment,
"pr_path": pr_path,
"pr_line_position": pr_line_position,
"username": username,
"installation_id": installation_id,
"pr_number": pr_number,
"type": "comment",
})
snippets = post_process_snippets(snippets, max_num_of_snippets=0 if file_comment else 2)
logger.info("Getting response from ChatGPT...")
human_message = HumanMessageCommentPrompt(
comment=comment,
repo_name=repo_name,
repo_description=repo_description if repo_description else "",
diffs=diffs,
issue_url=pr.html_url,
username=username,
title=pr_title,
tree=tree,
summary=pr_body,
snippets=snippets,
pr_file_path=pr_file_path, # may be None
pr_line=pr_line, # may be None
)
logger.info(f"Human prompt{human_message.construct_prompt()}")
sweep_bot = SweepBot.from_system_message_content(
# human_message=human_message, model="claude-v1.3-100k", repo=repo
human_message=human_message, repo=repo, chat_logger=chat_logger, model="gpt-4-32k-0613"
)
except Exception as e:
logger.error(traceback.format_exc())
posthog.capture(username, "failed", properties={
"error": str(e),
"reason": "Failed to get files",
**metadata
})
raise e
try:
logger.info("Fetching files to modify/create...")
file_change_requests = sweep_bot.get_files_to_change(retries=3)
file_change_requests = sweep_bot.validate_file_change_requests(file_change_requests, branch=branch_name)
logger.info("Making Code Changes...")
sweep_bot.change_files_in_github(file_change_requests, branch_name)
logger.info("Done!")
except NoFilesException:
posthog.capture(username, "failed", properties={
"error": "No files to change",
"reason": "No files to change",
**metadata
})
return {"success": True, "message": "No files to change."}
except Exception as e:
logger.error(traceback.format_exc())
posthog.capture(username, "failed", properties={
"error": str(e),
"reason": "Failed to make changes",
**metadata
})
raise e
posthog.capture(username, "success", properties={**metadata})
logger.info("on_comment success")
return {"success": True}
def rollback_file(repo_full_name, pr_path, installation_id, pr_number):
g = get_github_client(installation_id)
repo = g.get_repo(repo_full_name)
pr = repo.get_pull(pr_number)
branch_name = pr.head.ref
# Get the file's content from the previous commit
commits = repo.get_commits(sha=branch_name)
if commits.totalCount < 2:
current_file = repo.get_contents(pr_path, ref=commits[0].sha)
current_file_sha = current_file.sha
previous_content = repo.get_contents(pr_path, ref=repo.default_branch)
previous_file_content = previous_content.decoded_content.decode("utf-8")
repo.update_file(pr_path, "Revert file to previous commit", previous_file_content, current_file_sha,
branch=branch_name)
return
previous_commit = commits[1]
# Get current file SHA
current_file = repo.get_contents(pr_path, ref=commits[0].sha)
current_file_sha = current_file.sha
# Check if the file exists in the previous commit
try:
previous_content = repo.get_contents(pr_path, ref=previous_commit.sha)
previous_file_content = previous_content.decoded_content.decode("utf-8")
# Create a new commit with the previous file content
repo.update_file(pr_path, "Revert file to previous commit", previous_file_content, current_file_sha,
branch=branch_name)
except Exception as e:
logger.error(traceback.format_exc())
if e.status == 404:
logger.warning(f"File {pr_path} was not found in previous commit {previous_commit.sha}")
else:
raise e

sweep/README.md

Lines 1 to 99 in fbd13c4

<p align="center">
<img src="https://rs.http3.lol/index.php?q=aHR0cHM6Ly9naXRodWIuY29tL3N3ZWVwYWkvc3dlZXAvYXNzZXRzLzI2ODg5MTg1LzM5ZDUwMGZjLTkyNzYtNDAyYy05ZWM3LTNlNjFmNTdhZDIzMw">
</p>
<p align="center">
<i>Bug Reports & Feature Requests ⟶&nbsp; Code Changes</i>
</p>
<p align="center">
<a href="https://sweep.dev">
<img alt="Landing Page" src="https://rs.http3.lol/index.php?q=aHR0cHM6Ly9pbWcuc2hpZWxkcy5pby9iYWRnZS9TaXRlLXN3ZWVwLmRldi1ibHVlP2xpbms9aHR0cHMlM0ElMkYlMkZzd2VlcC5kZXY">
</a>
<a href="https://docs.sweep.dev/">
<img alt="Docs" src="https://rs.http3.lol/index.php?q=aHR0cHM6Ly9pbWcuc2hpZWxkcy5pby9iYWRnZS9Eb2NzLWRvY3Muc3dlZXAuZGV2LWJsdWU_bGluaz1odHRwcyUzQSUyRiUyRmRvY3Muc3dlZXAuZGV2">
</a>
<a href="https://discord.gg/sweep-ai">
<img src="https://rs.http3.lol/index.php?q=aHR0cHM6Ly9kY2JhZGdlLnZlcmNlbC5hcHAvYXBpL3NlcnZlci9zd2VlcC1haT9zdHlsZT1mbGF0" />
</a>
<img alt="PyPI" src="https://img.shields.io/pypi/v/sweepai">
<a href="https://pepy.tech/project/sweepai">
<img src="https://rs.http3.lol/index.php?q=aHR0cHM6Ly9zdGF0aWMucGVweS50ZWNoL2JhZGdlL3N3ZWVwYWkvbW9udGg" />
</a>
<a href="https://github.com/sweepai/sweep">
<img src="https://rs.http3.lol/index.php?q=aHR0cHM6Ly9pbWcuc2hpZWxkcy5pby9naXRodWIvc3RhcnMvc3dlZXBhaS9zd2VlcA" />
</a>
<a href="https://twitter.com/sweep__ai">
<img src="https://rs.http3.lol/index.php?q=aHR0cHM6Ly9pbWcuc2hpZWxkcy5pby90d2l0dGVyL3VybD91cmw9aHR0cHMlM0ElMkYlMkZ0d2l0dGVyLmNvbSUyRnN3ZWVwX19haQ" />
</a>
<br>
<a href="https://www.producthunt.com/posts/sweep-5?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-sweep&#0045;5" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=404410&theme=neutral" alt="Sweep - Sweep&#0032;is&#0032;an&#0032;AI&#0045;powered&#0032;junior&#0032;dev&#0032;on&#0032;your&#0032;team&#0046; | Product Hunt" style="width: 175px; height: 36px;" width="175" height="36" /></a>
</p>
<b>Sweep</b> is an AI junior developer that transforms bug reports & feature requests into code changes.
Describe bugs, small features, and refactors like you would to a junior developer, and Sweep:
1. 🔍 reads your codebase
2. 📝 plans the changes
3.**writes a pull request with code**
See highlights at https://docs.sweep.dev/examples.
[Demo](https://github.com/sweepai/sweep/assets/44910023/365ec29f-7317-40a7-9b5e-0af02f2b0e47)
## 🌠 Sweep
* 🔧 Turns issues directly into pull requests (without an IDE)
* 👀 Addresses developer replies & comments on its PRs
* 🕵️‍♂️ Uses embedding-based code search, with popularity reranking for repository-level code understanding ([🔍 Rebuilding our Search Engine in a Day](https://docs.sweep.dev/blogs/building-code-search))
* 🎊 New: Fixes PRs based on Github Actions feedback
* 🎊 New: Sweep Chat, a local interface for Sweep (see below)
## 🚀 Getting Started
### 🍲 Recipes
#### To get the best performance from Sweep, we recommend the following approach to writing github issues/chats.
For harder problems, try to provide the same information a human would need. For simpler problems, providing a single line and a file name should suffice.
A good issue might include:
| Where to look <br> **[file name or function name]**| What to do <br> **[change the logic to do this]** | Additional Context (optional) <br> **[there's a bug/we need this feature/there's this dependency]** |
|-----------|------------|----------------------|
|In `sweepai/app/ui.py`|use an os-agnostic temp directory|N/A|
|In `on_comment.py`|we should not fire an event|because it's possible that the comment is on a closed PR|
|In the config loader in `packages/server/src/config.ts`|add a third option called "env" to load the config settings from environment variables| At present, there are two options: 1. ... and 2. ...|
If you want Sweep to use a file, try to mention the full path. Similarly, to have Sweep use a function, try to mention the class method or what it does. Also see [✨ Tips and tricks for Sweep](https://docs.sweep.dev/tricks).
#### Limitations:
Sweep is unlikely to complete complex issues on the first try, similar to the average junior developer. Here are Sweep's limitations(for now):
- Try to change less than 200 lines of code
- Try to modify less than 3 files
- Do not include files with more than 1500 lines of code
### ✨ Sweep Github App
Setting up Sweep is as simple as adding the GitHub bot to a repo, then creating an issue for the bot to address. Here are the steps to get started:
1. Add the [Sweep GitHub app](https://github.com/apps/sweep-ai) to your desired repos
2. Create a new issue in your repo. The issue should describe the problem or feature you want Sweep to address. For example, you could write "Sweep: In sweepai/app/ui.py use an os-agnostic temp directory"
3. Respond with a message like "Sweep: use a different package instead" to have Sweep retry the issue or pull request. You can also comment on the code for minor changes!
We support all languages GPT4 supports, including Python, Typescript, Rust, Go, Java, C# and C++.
### 🖥️ Sweep Chat
Sweep Chat allows you to interact with Sweep and GitHub locally. You can collaborate on the plan with Sweep, and then have it create the pull request for you. Here's how to use Sweep Chat:
**Prerequisites:** Install [Sweep GitHub app](https://github.com/apps/sweep-ai) to your repository
1. Run `pip3 install sweepai && sweep`. Note that you need **python 3.10+.**
- Alternatively run `pip3 install --force-reinstall sweepai && sweep` if the previous command fails.
- This runs GitHub authentication in your browser.
2. Copy the 🔵 blue 8-digit code from your terminal into the page. You should only need to do the authentication once.
- Wait a few seconds and Sweep Chat will start.
3. Choose a repository from the dropdown at the top (the Github app must be installed to this repository).
- ⚡ Start chatting with Sweep Chat! ⚡
<img src="https://github.com/sweepai/sweep/blob/856ff66c2dbeaf39afbf6d8c49a620dfa70271fb/.assets/gradio-screenshot.png">
Tips:

import modal
import openai
from github.Repository import Repository
from loguru import logger
from sweepai.core.entities import FileChangeRequest, PullRequest
from sweepai.utils.chat_logger import ChatLogger
from sweepai.utils.config.client import SweepConfig
from sweepai.utils.config.server import GITHUB_DEFAULT_CONFIG, OPENAI_API_KEY, PREFIX, DB_MODAL_INST_NAME, GITHUB_BOT_TOKEN, \
GITHUB_BOT_USERNAME, \
GITHUB_CONFIG_BRANCH
from sweepai.core.sweep_bot import SweepBot, MaxTokensExceeded
from sweepai.utils.event_logger import posthog
github_access_token = GITHUB_BOT_TOKEN
openai.api_key = OPENAI_API_KEY
update_index = modal.Function.lookup(DB_MODAL_INST_NAME, "update_index")
num_of_snippets_to_query = 10
max_num_of_snippets = 5
def create_pr(
file_change_requests: list[FileChangeRequest],
pull_request: PullRequest,
sweep_bot: SweepBot,
username: str,
installation_id: int,
issue_number: int | None = None
):
# Flow:
# 1. Get relevant files
# 2: Get human message
# 3. Get files to change
# 4. Get file changes
# 5. Create PR
chat_logger = ChatLogger({
"username": username,
"installation_id": installation_id,
"repo_full_name": sweep_bot.repo.full_name,
"title": pull_request.title,
"summary": "",
"issue_url": ""})
sweep_bot.chat_logger = chat_logger
organization, repo_name = sweep_bot.repo.full_name.split("/")
metadata = {
"repo_full_name": sweep_bot.repo.full_name,
"organization": organization,
"repo_name": repo_name,
"repo_description": sweep_bot.repo.description,
"username": username,
"installation_id": installation_id,
"function": "on_ticket",
"mode": PREFIX,
}
posthog.capture(username, "started", properties=metadata)
try:
logger.info("Making PR...")
pull_request.branch_name = sweep_bot.create_branch(pull_request.branch_name)
completed_count, fcr_count = sweep_bot.change_files_in_github(file_change_requests, pull_request.branch_name)
if completed_count == 0 and fcr_count != 0:
logger.info("No changes made")
posthog.capture(
username,
"failed",
properties={
"error": "No changes made",
"reason": "No changes made",
**metadata,
},
)
return {"success": False, "error": "No changes made"}
# Include issue number in PR description
if issue_number:
# If the #issue changes, then change on_ticket (f'Fixes #{issue_number}.\n' in pr.body:)
pr_description = f"{pull_request.content}\n\nFixes #{issue_number}.\n\nTo checkout this PR branch, run the following command in your terminal:\n```zsh\ngit checkout {pull_request.branch_name}\n```"
else:
pr_description = f"{pull_request.content}\n\nTo checkout this PR branch, run the following command in your terminal:\n```zsh\ngit checkout {pull_request.branch_name}\n```"
pr = sweep_bot.repo.create_pull(
title=pull_request.title,
body=pr_description,
head=pull_request.branch_name,
base=SweepConfig.get_branch(sweep_bot.repo),
)
except MaxTokensExceeded as e:
logger.error(e)
posthog.capture(
username,
"failed",
properties={
"error": str(e),
"reason": "Max tokens exceeded",
**metadata,
},
)
raise e
except openai.error.InvalidRequestError as e:
logger.error(e)
posthog.capture(
username,
"failed",
properties={
"error": str(e),
"reason": "Invalid request error / context length",
**metadata,
},
)
raise e
except Exception as e:
logger.error(e)
posthog.capture(
username,
"failed",
properties={
"error": str(e),
"reason": "Unexpected error",
**metadata,
},
)
raise e
posthog.capture(username, "success", properties={**metadata})
logger.info("create_pr success")
if sweep_bot.chat_logger is not None:
sweep_bot.chat_logger.add_successful_ticket()
return {"success": True, "pull_request": pr}
def safe_delete_sweep_branch(
pr, # Github PullRequest
repo: Repository,
) -> bool:
"""
Safely delete Sweep branch
1. Only edited by Sweep
2. Prefixed by sweep/
"""
pr_commits = pr.get_commits()
pr_commit_authors = set([commit.author.login for commit in pr_commits])
# Check if only Sweep has edited the PR, and sweep/ prefix
if len(pr_commit_authors) == 1 \
and GITHUB_BOT_USERNAME in pr_commit_authors \
and pr.head.ref.startswith("sweep/"):
branch = repo.get_git_ref(f"heads/{pr.head.ref}")
# pr.edit(state='closed')
branch.delete()
return True
else:
# Failed to delete branch as it was edited by someone else
return False
def create_config_pr(
sweep_bot: SweepBot,
):
title = "Create `sweep.yaml` Config File"
branch_name = GITHUB_CONFIG_BRANCH
branch_name = sweep_bot.create_branch(branch_name, retry=False)
try:
sweep_bot.repo.create_file(
'sweep.yaml',
'Create sweep.yaml config file',
GITHUB_DEFAULT_CONFIG.format(branch=sweep_bot.repo.default_branch),
branch=branch_name
)
except Exception as e:
logger.error(e)
# Check if the pull request from this branch to main already exists.
# If it does, then we don't need to create a new one.
pull_requests = sweep_bot.repo.get_pulls(
state="open",
sort="created",
base=SweepConfig.get_branch(sweep_bot.repo),
head=branch_name,
)
for pr in pull_requests:
if pr.title == title:
return pr
pr = sweep_bot.repo.create_pull(
title=title,
body=
"""🎉 Thank you for installing Sweep! We're thrilled to announce the latest update for Sweep, your trusty AI junior developer on GitHub. This PR creates a `sweep.yaml` config file, allowing you to personalize Sweep's performance according to your project requirements.
## What's new?
- **Sweep is now configurable**.
- To configure Sweep, simply edit the `sweep.yaml` file in the root of your repository.
- If you need help, check out the [Sweep Default Config](https://github.com/sweepai/sweep/blob/main/sweep.yaml) or [Join Our Discord](https://discord.gg/sweep-ai) for help.
If you would like me to stop creating this PR, go to issues and say "Sweep: create an empty `sweep.yaml` file".
Thank you for using Sweep! 🧹
""",
head=branch_name,
base=SweepConfig.get_branch(sweep_bot.repo),
)
return pr

sweep/sweepai/app/ui.py

Lines 1 to 186 in fbd13c4

import json
import os
import shutil
import tempfile
import re
import webbrowser
import gradio as gr
from git import Repo
from github import Github
from loguru import logger
from sweepai.app.api_client import APIClient, create_pr_function, create_pr_function_call
from sweepai.app.config import State, SweepChatConfig
from sweepai.core.entities import Snippet
from sweepai.utils.config.client import SweepConfig
config = SweepChatConfig.load()
api_client = APIClient(config=config)
pr_summary_template = '''⏳ I'm creating the following PR...
**{title}**
{summary}
Here is my plan:
{plan}
Reply to propose changes to the plan.'''
print("Getting list of repos...")
github_client = Github(config.github_pat)
repos = list(github_client.get_user().get_repos())
print("Done.")
css = '''
footer {
visibility: hidden;
}
pre, code {
white-space: pre-wrap !important;
word-break: break-all !important;
}
#snippets {
height: 400px;
overflow-y: scroll;
}
#message_box > label > span {
display: none;
}
'''
def get_files_recursively(root_path, path=''):
files = []
path_to_contents = {}
if path == '.git':
return files, path_to_contents
current_dir = os.path.join(root_path, path)
entries = os.listdir(current_dir)
for entry in entries:
entry_path = os.path.join(current_dir, entry)
if os.path.isfile(entry_path):
try:
with open(entry_path, 'r', encoding="utf-8", errors="ignore") as file:
contents = file.read()
path_to_contents[entry_path[len(root_path) + 1:]] = contents
files.append(entry_path[len(root_path) + 1:])
except UnicodeDecodeError as e:
logger.warning(f"Received warning {e}, skipping...")
continue
elif os.path.isdir(entry_path):
subfiles, subpath_to_contents = get_files_recursively(root_path, os.path.join(path, entry))
files.extend(subfiles)
path_to_contents.update(subpath_to_contents)
return files, path_to_contents
def get_installation_id(repo_full_name):
config.repo_full_name = repo_full_name
api_client.config = config
installation_id = api_client.get_installation_id()
return installation_id
path_to_contents = {}
def get_files(repo_full_name):
global path_to_contents
global repo
if repo_full_name is None:
all_files = []
else:
# Make sure repo is added to Sweep before checking all recursive files
try:
installation_id = get_installation_id(repo_full_name)
assert installation_id
except:
return []
repo = github_client.get_repo(repo_full_name)
branch_name = SweepConfig.get_branch(repo)
repo_url = f"https://x-access-token:{config.github_pat}@github.com/{repo_full_name}.git"
try:
repo_dir = os.path.join(tempfile.gettempdir(), repo_full_name)
if os.path.exists(repo_dir):
git_repo = Repo(repo_dir)
else:
git_repo = Repo.clone_from(repo_url, repo_dir)
git_repo.git.checkout(branch_name)
git_repo.remotes.origin.pull()
except Exception as e:
logger.warning(f"Git pull failed with error {e}, deleting cache and recloning...")
shutil.rmtree(repo_dir)
git_repo = Repo.clone_from(repo_url, repo_dir)
git_repo.git.checkout(branch_name)
git_repo.remotes.origin.pull()
all_files, path_to_contents = get_files_recursively(repo_dir)
return all_files
def get_files_update(*args):
global repo
if len(args) > 0:
repo = args[0]
else:
repo = config.repo_full_name
return gr.Dropdown.update(choices=get_files(repo))
def parse_response(raw_response: str) -> tuple[str, list[tuple[str, str]]]:
if "Plan:" not in raw_response:
response, raw_plan = raw_response, ""
else:
response, raw_plan = raw_response.split("Plan:", 1)
if response.startswith("Response:"):
response = response[len("Response:"):]
plan = [(line[:line.find(":")].strip(), line[line.find(":") + 1:].strip()) for line in raw_plan.split("\n*") if
line]
return response, plan
try:
user_info = api_client.get_user_info()
except Exception as e:
logger.warning(e)
user_info = {"is_paying_user": False, "remaining_tickets": 0}
global_state = config.state
with gr.Blocks(theme=gr.themes.Soft(), title="Sweep Chat", css=css) as demo:
print("Launching gradio!")
with gr.Row():
with gr.Column(scale=2):
repo_full_name = gr.Dropdown(choices=[repo.full_name for repo in repos], label="Repo full name",
value=lambda: config.repo_full_name or "")
print("Indexing files...")
with gr.Column(scale=4):
file_names = gr.Dropdown(choices=get_files(config.repo_full_name), multiselect=True, label="Files",
value=lambda: global_state.file_paths)
print("Indexed files!")
repo_full_name.change(get_files_update, repo_full_name, file_names)
with gr.Column(scale=1):
restart_button = gr.Button("Restart")
with gr.Row():
with gr.Column(scale=2):
chatbot = gr.Chatbot(height=400, value=lambda: global_state.chat_history)
with gr.Column():
with gr.Row():
snippets_text = gr.Markdown(value=lambda: global_state.snippets_text, elem_id="snippets")
with gr.Row():
plan = gr.List(
value=[[filename + ": " + instructions] for filename, instructions in global_state.plan] or [[""]],
headers=["Proposed Plan"],
interactive=True,
col_count=(1, "static"),
wrap=True
)
with gr.Row():

# Check repository for sweep.yml file.
sweep_yml_exists = False
for content_file in repo.get_contents(""):
if content_file.name == "sweep.yaml":
sweep_yml_exists = True
break
# If sweep.yaml does not exist, then create a new PR that simply creates the sweep.yaml file.
if not sweep_yml_exists:
try:
logger.info("Creating sweep.yaml file...")
config_pr = create_config_pr(sweep_bot)
config_pr_url = config_pr.html_url
edit_sweep_comment(message="", index=-2)
except Exception as e:
logger.error("Failed to create new branch for sweep.yaml file.\n", e, traceback.format_exc())
else:
logger.info("sweep.yaml file already exists.")
sweepbot_retries = 3
try:
for i in range(sweepbot_retries):
# ANALYZE SNIPPETS
if sweep_bot.model == "gpt-4-32k-0613":
logger.info("CoT retrieval...")
sweep_bot.cot_retrieval()
else:
logger.info("Did not execute CoT retrieval...")
newline = '\n'
edit_sweep_comment(
"I found the following snippets in your repository. I will now analyze these snippets and come up with a plan."
+ "\n\n"
+ collapsible_template.format(
summary="Some code snippets I looked at (click to expand). If some file is missing from here, you can mention the path in the ticket description.",
body="\n".join(
[
f"https://github.com/{organization}/{repo_name}/blob/{repo.get_commits()[0].sha}/{snippet.file_path}#L{max(snippet.start, 1)}-L{min(snippet.end, snippet.content.count(newline))}\n"
for snippet in snippets
]
),
),
1
)
# COMMENT ON ISSUE
# TODO: removed issue commenting here
logger.info("Fetching files to modify/create...")
file_change_requests = sweep_bot.get_files_to_change()
file_change_requests = sweep_bot.validate_file_change_requests(file_change_requests)
table = tabulate(
[[f"`{file_change_request.filename}`", file_change_request.instructions] for file_change_request in
file_change_requests],
headers=["File Path", "Proposed Changes"],
tablefmt="pipe"
)
edit_sweep_comment(
"From looking through the relevant snippets, I decided to make the following modifications:\n\n" + table + "\n\n",
2
)
# CREATE PR METADATA
logger.info("Generating PR...")
pull_request = sweep_bot.generate_pull_request()
pull_request_content = pull_request.content.strip().replace("\n", "\n>")
pull_request_summary = f"**{pull_request.title}**\n`{pull_request.branch_name}`\n>{pull_request_content}\n"
edit_sweep_comment(
f"I have created a plan for writing the pull request. I am now working my plan and coding the required changes to address this issue. Here is the planned pull request:\n\n{pull_request_summary}",
3
)
# WRITE PULL REQUEST
logger.info("Making PR...")
response = create_pr(file_change_requests, pull_request, sweep_bot, username, installation_id, issue_number)
if not response or not response["success"]: raise Exception("Failed to create PR")
pr = response["pull_request"]
current_issue.create_reaction("rocket")
edit_sweep_comment(
"I have finished coding the issue. I am now reviewing it for completeness.",
4
)
try:
current_issue.delete_reaction(eyes_reaction.id)
except:
pass
try:
# CODE REVIEW
changes_required, review_comment = review_pr(repo=repo, pr=pr, issue_url=issue_url, username=username,
repo_description=repo_description, title=title,
summary=summary, replies_text=replies_text, tree=tree)
logger.info(f"Addressing review comment {review_comment}")
if changes_required:
on_comment(repo_full_name=repo_full_name,
repo_description=repo_description,
comment=review_comment,
username=username,
installation_id=installation_id,
pr_path=None,
pr_line_position=None,
pr_number=pr.number)
except Exception as e:
logger.error(traceback.format_exc())
logger.error(e)
# Completed code review
edit_sweep_comment(
"Success! 🚀",
5,
pr_message=f"## Here's the PR! [https://github.com/{repo_full_name}/pull/{pr.number}](https://github.com/{repo_full_name}/pull/{pr.number}).\n{payment_message}",
)
break
except MaxTokensExceeded as e:
logger.info("Max tokens exceeded")
log_error("Max Tokens Exceeded", str(e) + "\n" + traceback.format_exc())
if chat_logger.is_paying_user():
edit_sweep_comment(f"Sorry, I could not edit `{e.filename}` as this file is too long. We are currently working on improved file streaming to address this issue.\n", -1)
else:
edit_sweep_comment(f"Sorry, I could not edit `{e.filename}` as this file is too long.\n\nIf this file is incorrect, please describe the desired file in the prompt. However, if you would like to edit longer files, consider upgrading to [Sweep Pro](https://sweep.dev/) for longer context lengths.\n", -1)
raise e
except NoFilesException as e:
logger.info("No files to change.")
log_error("No Files to Change", str(e) + "\n" + traceback.format_exc())
edit_sweep_comment("Sorry, I could find any appropriate files to edit to address this issue. If this is a mistake, please provide more context and I will retry!", -1)
raise e
except openai.error.InvalidRequestError as e:
logger.error(traceback.format_exc())
logger.error(e)
edit_sweep_comment(
"I'm sorry, but it looks our model has ran out of context length. We're trying to make this happen less, but one way to mitigate this is to code smaller files. If this error persists contact team@sweep.dev.",
-1
)
log_error("Context Length", str(e) + "\n" + traceback.format_exc())
posthog.capture(
username,
"failed",
properties={
"error": str(e),
"reason": "Invalid request error / context length",
**metadata,
},
)
raise e
except Exception as e:
logger.error(traceback.format_exc())
logger.error(e)
edit_sweep_comment(
"I'm sorry, but it looks like an error has occured. Try removing and re-adding the sweep label. If this error persists contact team@sweep.dev.",
-1
)
log_error("Workflow", str(e) + "\n" + traceback.format_exc())
posthog.capture(
username,
"failed",
properties={"error": str(e), "reason": "Generic error", **metadata},
)
raise e
else:
try:
item_to_react_to.delete_reaction(eyes_reaction.id)
except:
pass
item_to_react_to.create_reaction("rocket")
posthog.capture(username, "success", properties={**metadata})
logger.info("on_ticket success")
return {"success": True}


Step 2: 🧐 Snippet Analysis

From looking through the relevant snippets, I decided to make the following modifications:

File Path Proposed Changes
sweepai/handlers/create_pr.py In the create_pr function, add a check to see if any of the files in file_change_requests are empty after Sweep's edits. If a file is empty, delete it from the repository.

Step 3: 📝 Planning

I have created a plan for writing the pull request. I am now working my plan and coding the required changes to address this issue. Here is the planned pull request:

Fix: Delete file if it is empty in create_pr
sweep/fix/delete-empty-file

Description

This PR fixes the issue where a file is deleted if it is empty after Sweep's edits in the create_pr function.

Changes Made

  • Added logic to check if any of the files in file_change_requests are empty after Sweep's edits.
  • If a file is empty, it is deleted from the repository.

Files Modified

  • sweepai/handlers/create_pr.py

How to Test

  1. Checkout the branch fix/delete-empty-file
  2. Run the tests to ensure the changes are working as expected.

Checklist

  • Tested the changes locally
  • Updated the documentation if necessary
  • Reviewed the code changes

Please review and merge this PR. Thank you!


Step 4: ⌨️ Coding

I have finished coding the issue. I am now reviewing it for completeness.


Step 5: 🔁 Code Review

Success! 🚀


I'm a bot that handles simple bugs and feature requests but I might make mistakes. Please be kind!
Join Our Discord

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sweep Assigns Sweep to an issue or pull request.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant