diff --git a/aider/coders/agent_coder.py b/aider/coders/agent_coder.py index c97bd041410..f11de0976a1 100644 --- a/aider/coders/agent_coder.py +++ b/aider/coders/agent_coder.py @@ -23,6 +23,7 @@ from aider.mcp.server import LocalServer from aider.repo import ANY_GIT_ERROR +# Import tool modules for registry # Import tool modules for registry from aider.tools import ( command, @@ -32,8 +33,10 @@ delete_lines, extract_lines, finished, + git_branch, git_diff, git_log, + git_remote, git_show, git_status, grep, @@ -159,8 +162,10 @@ def _build_tool_registry(self): delete_lines, extract_lines, finished, + git_branch, git_diff, git_log, + git_remote, git_show, git_status, grep, diff --git a/aider/tools/__init__.py b/aider/tools/__init__.py index c1b2f6c710d..60b3b06c5af 100644 --- a/aider/tools/__init__.py +++ b/aider/tools/__init__.py @@ -10,8 +10,10 @@ delete_lines, extract_lines, finished, + git_branch, git_diff, git_log, + git_remote, git_show, git_status, grep, @@ -43,8 +45,10 @@ delete_lines, extract_lines, finished, + git_branch, git_diff, git_log, + git_remote, git_show, git_status, grep, diff --git a/aider/tools/git_branch.py b/aider/tools/git_branch.py new file mode 100644 index 00000000000..6a8d2c75d3d --- /dev/null +++ b/aider/tools/git_branch.py @@ -0,0 +1,129 @@ +from aider.repo import ANY_GIT_ERROR + +schema = { + "type": "function", + "function": { + "name": "GitBranch", + "description": ( + "List branches in the repository with various filtering and formatting options." + ), + "parameters": { + "type": "object", + "properties": { + "remotes": { + "type": "boolean", + "description": "List remote-tracking branches (-r/--remotes flag)", + }, + "all": { + "type": "boolean", + "description": "List both local and remote branches (-a/--all flag)", + }, + "verbose": { + "type": "boolean", + "description": ( + "Show verbose information including commit hash and subject (-v flag)" + ), + }, + "very_verbose": { + "type": "boolean", + "description": ( + "Show very verbose information including upstream branch (-vv flag)" + ), + }, + "merged": { + "type": "string", + "description": "Show branches merged into specified commit (--merged flag)", + }, + "no_merged": { + "type": "string", + "description": ( + "Show branches not merged into specified commit (--no-merged flag)" + ), + }, + "sort": { + "type": "string", + "description": ( + "Sort branches by key (committerdate, authordate, refname, etc.) (--sort" + " flag)" + ), + }, + "format": { + "type": "string", + "description": "Custom output format using placeholders (--format flag)", + }, + "show_current": { + "type": "boolean", + "description": "Show only current branch name (--show-current flag)", + }, + }, + "required": [], + }, + }, +} + +# Normalized tool name for lookup +NORM_NAME = "gitbranch" + + +def _execute_git_branch(coder, params=None): + """ + List branches in the repository with various filtering and formatting options. + """ + if not coder.repo: + return "Not in a git repository." + + try: + # Build git command arguments + args = [] + + # Handle boolean flags + if params: + if params.get("remotes"): + args.append("--remotes") + if params.get("all"): + args.append("--all") + if params.get("verbose"): + args.append("--verbose") + if params.get("very_verbose"): + args.append("--verbose") + args.append("--verbose") + if params.get("show_current"): + args.append("--show-current") + + # Handle string parameters + if params.get("merged"): + args.extend(["--merged", params["merged"]]) + if params.get("no_merged"): + args.extend(["--no-merged", params["no_merged"]]) + if params.get("sort"): + args.extend(["--sort", params["sort"]]) + if params.get("format"): + args.extend(["--format", params["format"]]) + + # Execute git command + result = coder.repo.repo.git.branch(*args) + + # If no result and show_current was used, get current branch directly + if not result and params and params.get("show_current"): + current_branch = coder.repo.repo.active_branch.name + return current_branch + + return result if result else "No branches found matching the criteria." + + except ANY_GIT_ERROR as e: + coder.io.tool_error(f"Error running git branch: {e}") + return f"Error running git branch: {e}" + + +def process_response(coder, params): + """ + Process the GitBranch tool response. + + Args: + coder: The Coder instance + params: Dictionary of parameters for GitBranch + + Returns: + str: Result message + """ + return _execute_git_branch(coder, params) diff --git a/aider/tools/git_remote.py b/aider/tools/git_remote.py new file mode 100644 index 00000000000..5f839683c17 --- /dev/null +++ b/aider/tools/git_remote.py @@ -0,0 +1,53 @@ +from aider.repo import ANY_GIT_ERROR + +schema = { + "type": "function", + "function": { + "name": "GitRemote", + "description": "List remote repositories.", + "parameters": { + "type": "object", + "properties": {}, + "required": [], + }, + }, +} + +# Normalized tool name for lookup +NORM_NAME = "gitremote" + + +def _execute_git_remote(coder): + """ + List remote repositories. + """ + if not coder.repo: + return "Not in a git repository." + + try: + remotes = coder.repo.repo.remotes + if not remotes: + return "No remotes configured." + + result = [] + for remote in remotes: + result.append(f"{remote.name}\t{remote.url}") + return "\n".join(result) + except ANY_GIT_ERROR as e: + coder.io.tool_error(f"Error running git remote: {e}") + return f"Error running git remote: {e}" + + +def process_response(coder, params): + """ + Process the GitRemote tool response. + + Args: + coder: The Coder instance + params: Dictionary of parameters (should be empty for GitRemote) + + Returns: + str: Result message + """ + # GitRemote tool has no parameters to validate + return _execute_git_remote(coder)