diff --git a/src/codegen/extensions/langchain/tools.py b/src/codegen/extensions/langchain/tools.py index 2ab5b0179..85d7c0503 100644 --- a/src/codegen/extensions/langchain/tools.py +++ b/src/codegen/extensions/langchain/tools.py @@ -8,6 +8,7 @@ from codegen.extensions.linear.linear_client import LinearClient from codegen.extensions.tools.bash import run_bash_command from codegen.extensions.tools.github.checkout_pr import checkout_pr +from codegen.extensions.tools.github.view_commit_history import view_commit_history from codegen.extensions.tools.github.view_pr_checks import view_pr_checks from codegen.extensions.tools.linear.linear import ( linear_comment_on_issue_tool, @@ -629,6 +630,29 @@ def _run(self, pr_number: int) -> str: return result.render() +class GithubViewCommitHistoryInput(BaseModel): + """Input for viewing commit history.""" + + max_results: int = Field(default=20, description="Maximum number of commits to return") + path: str | None = Field(default=None, description="Optional path to filter commits by") + + +class GithubViewCommitHistoryTool(BaseTool): + """Tool for viewing commit history with URLs.""" + + name: ClassVar[str] = "view_commit_history" + description: ClassVar[str] = "View the commit history for a repository or specific path with URLs for linking" + args_schema: ClassVar[type[BaseModel]] = GithubViewCommitHistoryInput + codebase: Codebase = Field(exclude=True) + + def __init__(self, codebase: Codebase) -> None: + super().__init__(codebase=codebase) + + def _run(self, max_results: int = 20, path: str | None = None) -> str: + result = view_commit_history(self.codebase, max_results=max_results, path=path) + return result.render() + + ######################################################################################################################## # LINEAR ######################################################################################################################## @@ -838,6 +862,7 @@ def get_workspace_tools(codebase: Codebase) -> list["BaseTool"]: GithubCreatePRCommentTool(codebase), GithubCreatePRReviewCommentTool(codebase), GithubViewPRTool(codebase), + GithubViewCommitHistoryTool(codebase), GithubSearchIssuesTool(codebase), # Linear LinearGetIssueTool(codebase), diff --git a/src/codegen/extensions/tools/github/__init__.py b/src/codegen/extensions/tools/github/__init__.py index f5f9761f3..01c1fb531 100644 --- a/src/codegen/extensions/tools/github/__init__.py +++ b/src/codegen/extensions/tools/github/__init__.py @@ -2,6 +2,7 @@ from .create_pr_comment import create_pr_comment from .create_pr_review_comment import create_pr_review_comment from .search import search +from .view_commit_history import view_commit_history from .view_pr import view_pr __all__ = [ @@ -9,5 +10,6 @@ "create_pr_comment", "create_pr_review_comment", "search", + "view_commit_history", "view_pr", ] diff --git a/src/codegen/extensions/tools/github/view_commit_history.py b/src/codegen/extensions/tools/github/view_commit_history.py new file mode 100644 index 000000000..6e038de9c --- /dev/null +++ b/src/codegen/extensions/tools/github/view_commit_history.py @@ -0,0 +1,66 @@ +"""Tool for viewing commit history with URLs.""" + +from typing import ClassVar, Optional + +from pydantic import Field + +from codegen.sdk.core.codebase import Codebase + +from ..observation import Observation + + +class CommitHistoryObservation(Observation): + """Response from viewing commit history.""" + + commits: list[dict] = Field( + description="List of commits with their details including URLs", + ) + + str_template: ClassVar[str] = "Found {total} commits" + + @property + def total(self) -> int: + return len(self.commits) + + +def view_commit_history( + codebase: Codebase, + max_results: int = 20, + path: Optional[str] = None, +) -> CommitHistoryObservation: + """Get the commit history for a repository or specific path. + + Args: + codebase: The codebase to operate on + max_results: Maximum number of commits to return + path: Optional path to filter commits by + """ + try: + # Get the GitHub repo object + repo = codebase._op.remote_git_repo + + # Get commits + commits_data = [] + commits = repo.repo.get_commits(path=path) + + for commit in commits[:max_results]: + commit_data = { + "sha": commit.sha, + "message": commit.commit.message, + "author": commit.commit.author.name, + "date": commit.commit.author.date.isoformat(), + "url": commit.html_url, # Include the URL for linking + } + commits_data.append(commit_data) + + return CommitHistoryObservation( + status="success", + commits=commits_data, + ) + + except Exception as e: + return CommitHistoryObservation( + status="error", + error=f"Failed to get commit history: {e!s}", + commits=[], + )