Skip to content

Commit

Permalink
Restructre SWE Agent (#204)
Browse files Browse the repository at this point in the history
### **Description**
- Enhanced the `SubmitPatchRequest` and `SubmitPatch` class descriptions
to include details about the diff format.
- Simplified `CoderAgentArgs` initialization and updated method calls
across multiple files.
- Introduced `BaseSWEAgent` abstract class.
- Added `REVIEWER_BACKSTORY_TMPL` template for reviewer agent.
- Refactored `CoderAgent` to inherit from `BaseSWEAgent` and added
reviewer agent to the workflow.
- Added utility functions for logger setup and LLM retrieval.
- Updated README to include additional setup steps and environment
variables.
- Changed the patch generated to be static instead of agentic.

___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Enhancement
</strong></td><td><details><summary>8 files</summary><table>
<tr>
  <td>
    <details>
<summary><strong>submit_patch.py</strong><dd><code>Improve patch
submission descriptions and examples</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; </dd></summary>
<hr>
      

python/composio/local_tools/local_workspace/submit_patch/actions/submit_patch.py

<li>Enhanced the <code>SubmitPatchRequest</code> and
<code>SubmitPatch</code> class descriptions to <br>include details about
the diff format.<br>


</details>
    

  </td>
<td><a
href="https://github.com/ComposioHQ/composio/pull/204/files#diff-eb4ff8e8a15704392fa1a2d3795544db0b1f85b04299099ca1d67bb0395a4d43">+11/-2</a>&nbsp;
&nbsp; </td>

</tr>                    

<tr>
  <td>
    <details>
<summary><strong>run_evaluation.py</strong><dd><code>Simplify
CoderAgentArgs initialization and method call</code>&nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>
      
python/composio_swe/benchmark/run_evaluation.py

<li>Simplified <code>CoderAgentArgs</code> initialization by removing
redundant <br>parameters.<br> <li> Updated <code>coder.run</code> method
to accept <code>issue_config</code>.<br>


</details>
    

  </td>
<td><a
href="https://github.com/ComposioHQ/composio/pull/204/files#diff-d97c3a8fcc8931e4bc7bd8a5fd22231faf0ffd60133f65afb29ce91ee372ca87">+2/-6</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>                    

<tr>
  <td>
    <details>
<summary><strong>base_swe_agent.py</strong><dd><code>Add BaseSWEAgent
abstract class</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>
      
python/composio_swe/composio_swe/agent/base_swe_agent.py

<li>Introduced <code>BaseSWEAgent</code> abstract class with an abstract
<code>run</code> method.<br>


</details>
    

  </td>
<td><a
href="https://github.com/ComposioHQ/composio/pull/204/files#diff-8b58d3656c4f5dce0d84109cfd9952e5d55c3c3075c4bb18bd26e2840896100b">+12/-0</a>&nbsp;
&nbsp; </td>

</tr>                    

<tr>
  <td>
    <details>
<summary><strong>prompts.py</strong><dd><code>Add reviewer backstory
template</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>
      
python/composio_swe/composio_swe/agent/prompts.py

- Added `REVIEWER_BACKSTORY_TMPL` template for reviewer agent.



</details>
    

  </td>
<td><a
href="https://github.com/ComposioHQ/composio/pull/204/files#diff-a95507b8fd735f05687d8673e16728d15b6099e5f5a3ec9313f1afb3d3ec0a27">+12/-0</a>&nbsp;
&nbsp; </td>

</tr>                    

<tr>
  <td>
    <details>
<summary><strong>swe.py</strong><dd><code>Refactor CoderAgent and add
reviewer agent</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>
      
python/composio_swe/composio_swe/agent/swe.py

<li>Refactored <code>CoderAgent</code> to inherit from
<code>BaseSWEAgent</code>.<br> <li> Moved logger setup and LLM retrieval
to <code>utils.py</code>.<br> <li> Added reviewer agent and task to the
workflow.<br>


</details>
    

  </td>
<td><a
href="https://github.com/ComposioHQ/composio/pull/204/files#diff-bbb8fcd0bfdb219cf4e20ffd41e3695abb277d9a5efc2c5a315e478976655540">+59/-80</a>&nbsp;
</td>

</tr>                    

<tr>
  <td>
    <details>
<summary><strong>swe_run.py</strong><dd><code>Update CoderAgentArgs
initialization and method call</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>
      
python/composio_swe/composio_swe/agent/swe_run.py

<li>Updated <code>CoderAgentArgs</code> initialization to remove
redundant parameters.<br> <li> Updated <code>coder_agent.run</code>
method to accept <code>issue_config</code>.<br>


</details>
    

  </td>
<td><a
href="https://github.com/ComposioHQ/composio/pull/204/files#diff-784e85fde02b297e5d9c252831add5cfe880f537076facd0cd3f90ac62121e86">+4/-5</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>                    

<tr>
  <td>
    <details>
<summary><strong>utils.py</strong><dd><code>Add utility functions for
logger and LLM</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>
      
python/composio_swe/composio_swe/agent/utils.py

- Added utility functions for logger setup and LLM retrieval.



</details>
    

  </td>
<td><a
href="https://github.com/ComposioHQ/composio/pull/204/files#diff-ebba6012e3781136b15802f8496f063323a2d11aba51c645d1d8a5819486dab2">+34/-0</a>&nbsp;
&nbsp; </td>

</tr>                    

<tr>
  <td>
    <details>
<summary><strong>cli.py</strong><dd><code>Simplify solve command
initialization and method call</code>&nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>
      
python/composio_swe/composio_swe/cli/cli.py

<li>Updated <code>solve</code> command to simplify
<code>CoderAgentArgs</code> initialization and <br>method call.<br>


</details>
    

  </td>
<td><a
href="https://github.com/ComposioHQ/composio/pull/204/files#diff-9cb2bb57d930a1d094b58d1dba3b28334c6b806db91bb30ad984da874a046322">+5/-6</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>                    
</table></details></td></tr><tr><td><strong>Documentation
</strong></td><td><details><summary>1 files</summary><table>
<tr>
  <td>
    <details>
<summary><strong>README.md</strong><dd><code>Update README with
additional setup steps</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>
      
python/composio_swe/composio_swe/agent/README.md

<li>Updated README to include additional setup steps and environment
<br>variables.<br>


</details>
    

  </td>
<td><a
href="https://github.com/ComposioHQ/composio/pull/204/files#diff-3ee62cdba3c5db57de103a824f94d873c44d8a03368853305b126b5d5e665ec0">+14/-6</a>&nbsp;
&nbsp; </td>

</tr>                    
</table></details></td></tr></tr></tbody></table>

___

> 💡 **PR-Agent usage**:
>Comment `/help` on the PR to get a list of all available PR-Agent tools
and their descriptions
  • Loading branch information
kaavee315 authored Jun 24, 2024
1 parent ca96505 commit 702abbf
Show file tree
Hide file tree
Showing 17 changed files with 594 additions and 205 deletions.
50 changes: 27 additions & 23 deletions python/composio/client/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -7221,19 +7221,19 @@ def from_app_and_action(cls, app: str, name: str) -> "Action":
GMAIL_LIST_LABELS = ("gmail", "gmail_list_labels", False)
GMAIL_REPLY_TO_THREAD = ("gmail", "gmail_reply_to_thread", False)
GMAIL_SEND_EMAIL = ("gmail", "gmail_send_email", False)
GOOGLECALENDAR_CREATE_GOOGLE_EVENT = (
GOOGLECALENDAR_CREATE_EVENT = (
"googlecalendar",
"googlecalendar_create_google_event",
"googlecalendar_create_event",
False,
)
GOOGLECALENDAR_DELETE_GOOGLE_EVENT = (
GOOGLECALENDAR_DELETE_EVENT = (
"googlecalendar",
"googlecalendar_delete_google_event",
"googlecalendar_delete_event",
False,
)
GOOGLECALENDAR_DUPLICATE_GOOGLE_CALENDAR = (
GOOGLECALENDAR_DUPLICATE_CALENDAR = (
"googlecalendar",
"googlecalendar_duplicate_google_calendar",
"googlecalendar_duplicate_calendar",
False,
)
GOOGLECALENDAR_FIND_EVENT = ("googlecalendar", "googlecalendar_find_event", False)
Expand All @@ -7247,29 +7247,25 @@ def from_app_and_action(cls, app: str, name: str) -> "Action":
"googlecalendar_get_current_date_time",
False,
)
GOOGLECALENDAR_LIST_GOOGLE_CALENDARS = (
GOOGLECALENDAR_LIST_CALENDARS = (
"googlecalendar",
"googlecalendar_list_google_calendars",
"googlecalendar_list_calendars",
False,
)
GOOGLECALENDAR_PATCH_GOOGLE_CALENDAR = (
GOOGLECALENDAR_PATCH_CALENDAR = (
"googlecalendar",
"googlecalendar_patch_google_calendar",
False,
)
GOOGLECALENDAR_QUICK_ADD_GOOGLE_CALENDAR = (
"googlecalendar",
"googlecalendar_quick_add_google_calendar",
"googlecalendar_patch_calendar",
False,
)
GOOGLECALENDAR_QUICK_ADD = ("googlecalendar", "googlecalendar_quick_add", False)
GOOGLECALENDAR_REMOVE_ATTENDEE = (
"googlecalendar",
"googlecalendar_remove_attendee",
False,
)
GOOGLECALENDAR_UPDATE_GOOGLE_EVENT = (
GOOGLECALENDAR_UPDATE_EVENT = (
"googlecalendar",
"googlecalendar_update_google_event",
"googlecalendar_update_event",
False,
)
GOOGLEDOCS_CREATE_DOCUMENT = ("googledocs", "googledocs_create_document", False)
Expand Down Expand Up @@ -13830,12 +13826,6 @@ def from_app_and_action(cls, app: str, name: str) -> "Action":
True,
True,
)
CMDMANAGERTOOL_GITREPOTREE = (
"cmdmanagertool",
"cmdmanagertool_gitrepotree",
True,
True,
)
CMDMANAGERTOOL_EDITFILE = ("cmdmanagertool", "cmdmanagertool_editfile", True, True)
CMDMANAGERTOOL_RUNCOMMANDONWORKSPACE = (
"cmdmanagertool",
Expand All @@ -13855,6 +13845,18 @@ def from_app_and_action(cls, app: str, name: str) -> "Action":
True,
True,
)
CMDMANAGERTOOL_GITREPOTREE = (
"cmdmanagertool",
"cmdmanagertool_gitrepotree",
True,
True,
)
CMDMANAGERTOOL_GETPATCHCMD = (
"cmdmanagertool",
"cmdmanagertool_getpatchcmd",
True,
True,
)
HISTORYKEEPER_GETWORKSPACEHISTORY = (
"historykeeper",
"historykeeper_getworkspacehistory",
Expand Down Expand Up @@ -13904,6 +13906,8 @@ def event(self) -> str:
GITHUB_ISSUE_ADDED_EVENT = ("github", "github_issue_added_event")
GITHUB_LABEL_ADDED_EVENT = ("github", "github_label_added_event")
GITHUB_PULL_REQUEST_EVENT = ("github", "github_pull_request_event")
GITHUB_STAR_ADDED_EVENT = ("github", "github_star_added_event")
GMAIL_NEW_GMAIL_MESSAGE = ("gmail", "gmail_new_gmail_message")
GOOGLEDRIVE_GOOGLE_DRIVE_CHANGES = (
"googledrive",
"googledrive_google_drive_changes",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .clone_github import GithubCloneCmd
from .cmds import CreateFileCmd, GoToLineNumInOpenFile, OpenFile
from .edit_cmd import EditFile
from .get_patch import GetPatchCmd
from .git_tree import GitRepoTree
from .run_cmd import RunCommandOnWorkspace
from .scroll_cmds import Scroll
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ class GithubCloneRequest(BaseRequest):
description="after cloning the git repo, repo will be set to this commit-id."
"if commit-id is empty, default branch of the repo will be cloned",
)
just_reset: bool = Field(
False,
description="If true, the repo will not be cloned. It will be assumed to exist. The repo will be cleaned and reset to the given commit-id",
)


class GithubCloneResponse(BaseResponse):
Expand All @@ -51,6 +55,11 @@ class GithubCloneCmd(BaseAction):
def execute(
self, request_data: GithubCloneRequest, authorisation_data: dict
) -> BaseResponse:
if request_data.just_reset:
print("Resetting repository to base commit")
self.reset_to_base_commit(request_data)
return BaseResponse(output="Repository reset to base commit", return_code=0)

if not request_data.repo_name or not request_data.repo_name.strip():
raise ValueError("repo_name can not be null. Give a repo_name to clone")

Expand Down Expand Up @@ -81,3 +90,32 @@ def execute(
)
output, return_code = process_output(output, return_code)
return BaseResponse(output=output, return_code=return_code)

def reset_to_base_commit(self, request_data: GithubCloneRequest) -> None:
"""
Resets the repository to the specified base commit and cleans any untracked files or changes.
Assumes the repository already exists as cloned by the execute function.
"""
print("Resetting repository to base commit inside reset_to_base_commit")
self._setup(request_data)
# repo_dir = request_data.repo_name.split("/")[-1].strip()
reset_commands = [
"git fetch --all",
f"git reset --hard {request_data.commit_id}",
"git clean -fdx",
]
if self.container_process is None:
raise ValueError("Container process is not set")
print("Resetting repository to base commit checked container process")
reset_command = " && ".join(reset_commands)
output, return_code = communicate(
self.container_process,
self.container_obj,
reset_command,
self.parent_pids,
timeout_duration=LONG_TIMEOUT,
)
print(f"Resetting repository to base commit output: {output}")
if return_code != 0:
raise RuntimeError(f"Failed to reset repository: {output}")
print("Repository successfully reset to base commit and cleaned.")
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import typing as t

from pydantic import Field

from composio.local_tools.local_workspace.commons.get_logger import get_logger
from composio.local_tools.local_workspace.commons.history_processor import (
history_recorder,
)
from composio.local_tools.local_workspace.commons.local_docker_workspace import (
communicate,
)
from composio.local_tools.local_workspace.commons.utils import process_output

from .base_class import BaseAction, BaseRequest, BaseResponse


LONG_TIMEOUT = 200
logger = get_logger()


class GetPatchRequest(BaseRequest):
new_file_path: t.List[str] = Field(
default=[],
description="Paths of the files newly created to be included in the patch.",
)


class GetPatchResponse(BaseResponse):
pass


class GetPatchCmd(BaseAction):
"""
Get the patch from the current working directory. The patch is present in the output field of the response.
The patch is in the format of a proper diff format.
It incorporates any new files specified in the request, thereby excluding irrelevant installation files.
It includes deleted files by default.
You should run it after
Example:
diff --git a/repo/example.py b/repo/example.py
index 1234567..89abcde 100644
--- a/repo/example.py
+++ b/repo/example.py
@@ -1 +1 @@
-Hello, World!
+Hello, Composio!
"""

_history_maintains: bool = True
_display_name = "Get Patch Action"
_request_schema = GetPatchRequest
_response_schema = GetPatchResponse

@history_recorder()
def execute(
self, request_data: GetPatchRequest, authorisation_data: dict
) -> BaseResponse:
print("Get patch command...")
self._setup(request_data)
print("Setup completed.")
if self.container_process is None:
raise ValueError("Container process is not set")
new_files = " ".join(request_data.new_file_path)
cmd1 = "git add -u"
if len(request_data.new_file_path) > 0:
cmd1 = f"git add {new_files} && " + cmd1
output, return_code = communicate(
self.container_process, self.container_obj, cmd1, self.parent_pids
)
output, return_code = process_output(output, return_code)
print(f"Output of git add: {output}")
cmd2 = "git diff --cached"
output, return_code = communicate(
self.container_process, self.container_obj, cmd2, self.parent_pids
)
output, return_code = process_output(output, return_code)
return BaseResponse(
output=output,
return_code=return_code,
)
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ def execute(
self.container_process, self.container_obj, self.command, self.parent_pids
)
output, return_code = process_output(output, return_code)
files = output.split("\n")
return BaseResponse(
output=files,
output="Check git_repo_tree.txt for the git-repo-tree results. Use Open File function to check the file.",
return_code=return_code,
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
EditFile,
FindFileCmd,
GetCurrentDirCmd,
GetPatchCmd,
GitRepoTree,
GithubCloneCmd,
GoToLineNumInOpenFile,
Expand Down Expand Up @@ -43,6 +44,7 @@ def actions(self) -> list:
GetCurrentDirCmd,
GithubCloneCmd,
GitRepoTree,
GetPatchCmd,
]

def triggers(self) -> list:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ class SubmitPatchRequest(BaseModel):
workspace_id: str = Field(
..., description="workspace-id for which patch is generated"
)
patch_code: str = Field(..., description="patch code that needs to be submitted")
patch_code: str = Field(
...,
description="patch code that needs to be submitted - this should be a valid patch in diff format for the workspace.",
)


class SubmitPatchResponse(BaseModel):
Expand All @@ -28,7 +31,13 @@ class SubmitPatchResponse(BaseModel):

class SubmitPatch(Action):
"""
Submits generated patch for the workspace that should work
Submits generated patch for the workspace that should work This should be in diff format.
Example:
--- a/file.txt
+++ b/file.txt
@@ -1,3 +1,3 @@
-Hello, World!
+Hello, Python!
"""

_history_maintains = True
Expand Down
Loading

0 comments on commit 702abbf

Please sign in to comment.