diff --git a/python/composio/local_tools/local_workspace/cmd_manager/actions/clone_github.py b/python/composio/local_tools/local_workspace/cmd_manager/actions/clone_github.py index ec1bf1abb..dd1a19c93 100644 --- a/python/composio/local_tools/local_workspace/cmd_manager/actions/clone_github.py +++ b/python/composio/local_tools/local_workspace/cmd_manager/actions/clone_github.py @@ -100,6 +100,7 @@ def reset_to_base_commit(self, request_data: GithubCloneRequest) -> None: self._setup(request_data) # repo_dir = request_data.repo_name.split("/")[-1].strip() reset_commands = [ + "git remote get-url origin", "git fetch --all", f"git reset --hard {request_data.commit_id}", "git clean -fdx", diff --git a/python/composio/local_tools/local_workspace/tests/test_workspace.py b/python/composio/local_tools/local_workspace/tests/test_workspace.py index 3f9491877..26c336859 100644 --- a/python/composio/local_tools/local_workspace/tests/test_workspace.py +++ b/python/composio/local_tools/local_workspace/tests/test_workspace.py @@ -3,6 +3,22 @@ import pytest +from composio.local_tools.local_workspace.cmd_manager.actions.clone_github import ( + GithubCloneCmd, + GithubCloneRequest, +) +from composio.local_tools.local_workspace.cmd_manager.actions.cmds import ( + OpenCmdRequest, + OpenFile, +) +from composio.local_tools.local_workspace.cmd_manager.actions.edit_cmd import ( + EditFile, + EditFileRequest, +) +from composio.local_tools.local_workspace.cmd_manager.actions.get_patch import ( + GetPatchCmd, + GetPatchRequest, +) from composio.local_tools.local_workspace.cmd_manager.actions.search_cmds import ( GetCurrentDirCmd, GetCurrentDirRequest, @@ -24,8 +40,8 @@ condition=os.environ.get("CI") is not None, reason="no way of currently testing this in github action", ) -class TestCreateWorkspaceAction(unittest.TestCase): - def test_create_workspace(self): +class TestWorkspaceGitWorkflow(unittest.TestCase): + def test_git_workflow(self): # Setup - create an instance of CreateWorkspaceAction w = WorkspaceManagerFactory() h = HistoryProcessor() @@ -39,6 +55,120 @@ def test_create_workspace(self): # Verify - Check if the workspace was created successfully self.assertIsNotNone(result.workspace_id) + workspace_id = result.workspace_id + + action = GithubCloneCmd() + action.set_workspace_and_history(w, h) + github_clone_result = action.execute( + GithubCloneRequest( + repo_name="kaavee315/ML_assignment", + workspace_id=workspace_id, + commit_id="", + just_reset=False, + ), + {}, + ) + self.assertIsNotNone(github_clone_result) + + action = GithubCloneCmd() + action.set_workspace_and_history(w, h) + github_clone_result = action.execute( + GithubCloneRequest( + repo_name="kaavee315/ML_assignment", + workspace_id=workspace_id, + commit_id="", + just_reset=False, + ), + {}, + ) + self.assertIsNotNone(github_clone_result) + + action = OpenFile() + action.set_workspace_and_history(w, h) + open_file_result = action.execute( + OpenCmdRequest( + file_name="README.md", + workspace_id=workspace_id, + ), + {}, + ) + self.assertIsNotNone(open_file_result) + print("Open File 1 result: ", open_file_result) + + action = EditFile() + action.set_workspace_and_history(w, h) + edit_file_result = action.execute( + EditFileRequest( + start_line=1, + end_line=1, + replacement_text="print('Hello, World!')", + workspace_id=workspace_id, + ), + {}, + ) + self.assertIsNotNone(edit_file_result) + print("Edit File result: ", edit_file_result) + + action = OpenFile() + action.set_workspace_and_history(w, h) + open_file_result = action.execute( + OpenCmdRequest( + file_name="README.md", + workspace_id=workspace_id, + ), + {}, + ) + self.assertIsNotNone(open_file_result) + print("Open File 2 result: ", open_file_result) + + action = GetPatchCmd() + action.set_workspace_and_history(w, h) + get_patch_result = action.execute( + GetPatchRequest( + workspace_id=workspace_id, + ), + {}, + ) + self.assertIsNotNone(get_patch_result) + self.assertIsInstance(get_patch_result, tuple) + self.assertIsInstance(tuple(get_patch_result)[0], tuple) + patch_content = ( + tuple(tuple(get_patch_result)[0])[1] + if isinstance(tuple(tuple(get_patch_result)[0])[1], str) + else str(tuple(tuple(get_patch_result)[0])[1]) + ) + self.assertIn("Hello", patch_content) + self.assertIn("README", patch_content) + self.assertIn("diff", patch_content) + + action = GithubCloneCmd() + action.set_workspace_and_history(w, h) + github_reset_result = action.execute( + GithubCloneRequest( + repo_name="kaavee315/ML_assignment", + workspace_id=workspace_id, + commit_id="", + just_reset=True, + ), + {}, + ) + print("Github Reset result: ", github_reset_result) + self.assertIsNotNone(github_reset_result) + + action = OpenFile() + action.set_workspace_and_history(w, h) + open_file_result = action.execute( + OpenCmdRequest( + file_name="README.md", + workspace_id=workspace_id, + ), + {}, + ) + self.assertIsNotNone(open_file_result) + print("Open File result: ", open_file_result) + + # Check that the file content doesn't contain "Hello, World!" + self.assertNotIn("Hello", open_file_result) @pytest.mark.skipif( diff --git a/python/examples/swe/evaluation/visualize.py b/python/examples/swe/evaluation/visualize.py index 9442e16bb..2b70d803a 100644 --- a/python/examples/swe/evaluation/visualize.py +++ b/python/examples/swe/evaluation/visualize.py @@ -1,8 +1,9 @@ import json +import sys def load_logs(file_path): - with open(file_path, 'r') as file: + with open(file_path, "r") as file: return json.load(file) # Load the entire JSON file containing all issues @@ -11,27 +12,29 @@ def extract_details(agent_logs): for log in agent_logs: # from pprint import pprint # pprint(log) - if log['agent_action'] == 'agent_finish': + if log["agent_action"] == "agent_finish": agent_action = "agent_finish" - agent_output = log['agent_output'] + agent_output = log["agent_output"] else: - agent_action = json.loads(log['agent_action']) - tool_name = agent_action.get('tool', 'N/A') - tool_input = agent_action.get('tool_input', 'N/A') - tool_output = log.get('tool_output', 'N/A') - agent_thought = agent_action.get('log', 'No thoughts recorded') - - data.append({ - 'tool_name': tool_name or agent_action, - 'tool_input': tool_input, - 'tool_output': tool_output or agent_output, - 'agent_thought': agent_thought - }) + agent_action = json.loads(log["agent_action"]) + tool_name = agent_action.get("tool", "N/A") + tool_input = agent_action.get("tool_input", "N/A") + tool_output = log.get("tool_output", "N/A") + agent_thought = agent_action.get("log", "No thoughts recorded") + + data.append( + { + "tool_name": tool_name or agent_action, + "tool_input": tool_input, + "tool_output": tool_output or agent_output, + "agent_thought": agent_thought, + } + ) return data def generate_html_1(issues_data, output_file): - html_content = ''' + html_content = """ Agent Action Report by Issue @@ -44,10 +47,10 @@ def generate_html_1(issues_data, output_file):

Agent Action Report by Issue

- ''' + """ for issue, data in issues_data.items(): - html_content += f'

{issue}

' - html_content += ''' + html_content += f"

{issue}

" + html_content += """ @@ -55,29 +58,29 @@ def generate_html_1(issues_data, output_file): - ''' + """ for entry in data: - html_content += f''' + html_content += f""" - ''' - html_content += '
Tool NameTool Output Agent Thought
{entry['tool_name']} {entry['tool_input']} {entry['tool_output']} {entry['agent_thought']}
' - html_content += ''' + """ + html_content += "" + html_content += """ - ''' + """ - with open(output_file, 'w') as file: + with open(output_file, "w") as file: file.write(html_content) print(f"HTML report generated: {output_file}") def generate_html1(issues_data, output_file): - html_content = ''' + html_content = """ Agent Action Report by Issue @@ -107,9 +110,9 @@ def generate_html1(issues_data, output_file):

Agent Action Report by Issue

- ''' + """ for issue_idx, (issue, data) in enumerate(issues_data.items()): - html_content += f''' + html_content += f"""
@@ -119,10 +122,10 @@ def generate_html1(issues_data, output_file): - ''' + """ for entry_idx, entry in enumerate(data): tool_output_id = f"tool-output-content-{issue_idx}-{entry_idx}" - html_content += f''' + html_content += f""" @@ -132,10 +135,10 @@ def generate_html1(issues_data, output_file): - ''' - html_content += '
Tool Output Agent Thought
{entry['tool_name']} {entry['tool_input']} {entry['agent_thought']}
' + """ + html_content += "" - html_content += ''' + html_content += """ - ''' + """ - with open(output_file, 'w') as file: + with open(output_file, "w") as file: file.write(html_content) print(f"HTML report generated: {output_file}") - - def format_thought(thought): # print(thought) # Initial setup for default values if any of the parts are missing @@ -189,9 +190,8 @@ def format_thought(thought): return f'
Action: {action}
Action Input: {action_input}
Thought: {thought_text}
' - def generate_html(issues_data, output_file): - html_content = ''' + html_content = """ Agent Action Report by Issue @@ -219,18 +219,22 @@ def generate_html(issues_data, output_file):

Agent Action Report by Issue

- ''' + """ for issue_idx, (issue, data) in enumerate(issues_data.items()): - html_content += f'

{issue}

' + html_content += f"

{issue}

Tool NameTool InputTool OutputAgent Thought
" for entry_idx, entry in enumerate(data): content_id = f"content-{issue_idx}-{entry_idx}" - short_output = (entry['tool_output'][:75] + '...') if len(entry['tool_output']) > 78 else entry['tool_output'] - formatted_thought = format_thought(entry['agent_thought']) + short_output = ( + (entry["tool_output"][:75] + "...") + if len(entry["tool_output"]) > 78 + else entry["tool_output"] + ) + formatted_thought = format_thought(entry["agent_thought"]) html_content += f'' - html_content += '
Tool NameTool InputTool OutputAgent Thought
{entry["tool_name"]}{entry["tool_input"]}{short_output}
{entry["tool_output"]}
{formatted_thought}
' - html_content += '' + html_content += "" + html_content += "" - with open(output_file, 'w') as file: + with open(output_file, "w") as file: file.write(html_content) print(f"HTML report generated: {output_file}") @@ -242,6 +246,7 @@ def main(log_file_path, output_html_file): if __name__ == "__main__": - log_file_path = "" + + log_file_path = sys.argv[1] output_html_file = "agent_action_report_by_issue.html" # Desired output HTML file main(log_file_path, output_html_file)