elizaos-plugin-github 2.0.0a4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,113 @@
1
+ from elizaos_plugin_github.config import GitHubConfig
2
+ from elizaos_plugin_github.error import (
3
+ BranchExistsError,
4
+ BranchNotFoundError,
5
+ ClientNotInitializedError,
6
+ ConfigError,
7
+ FileNotFoundError,
8
+ GitHubApiError,
9
+ GitHubError,
10
+ InvalidArgumentError,
11
+ IssueNotFoundError,
12
+ MergeConflictError,
13
+ MissingSettingError,
14
+ NetworkError,
15
+ PermissionDeniedError,
16
+ PullRequestNotFoundError,
17
+ RateLimitedError,
18
+ RepositoryNotFoundError,
19
+ TimeoutError,
20
+ ValidationError,
21
+ )
22
+ from elizaos_plugin_github.service import GitHubService
23
+ from elizaos_plugin_github.types import (
24
+ CreateBranchParams,
25
+ CreateCommentParams,
26
+ CreateCommitParams,
27
+ CreateIssueParams,
28
+ CreatePullRequestParams,
29
+ CreateReviewParams,
30
+ FileChange,
31
+ GitHubBranch,
32
+ GitHubComment,
33
+ GitHubCommit,
34
+ GitHubDirectoryEntry,
35
+ GitHubEventType,
36
+ GitHubFileContent,
37
+ GitHubIssue,
38
+ GitHubLabel,
39
+ GitHubMilestone,
40
+ GitHubPullRequest,
41
+ GitHubRepository,
42
+ GitHubReview,
43
+ GitHubUser,
44
+ IssueState,
45
+ ListIssuesParams,
46
+ ListPullRequestsParams,
47
+ MergePullRequestParams,
48
+ PullRequestState,
49
+ RepositoryRef,
50
+ ReviewState,
51
+ UpdateIssueParams,
52
+ UpdatePullRequestParams,
53
+ )
54
+
55
+ __all__ = [
56
+ # Config
57
+ "GitHubConfig",
58
+ # Errors
59
+ "GitHubError",
60
+ "ClientNotInitializedError",
61
+ "ConfigError",
62
+ "MissingSettingError",
63
+ "InvalidArgumentError",
64
+ "RepositoryNotFoundError",
65
+ "BranchNotFoundError",
66
+ "FileNotFoundError",
67
+ "IssueNotFoundError",
68
+ "PullRequestNotFoundError",
69
+ "PermissionDeniedError",
70
+ "RateLimitedError",
71
+ "MergeConflictError",
72
+ "BranchExistsError",
73
+ "ValidationError",
74
+ "GitHubApiError",
75
+ "NetworkError",
76
+ "TimeoutError",
77
+ # Types
78
+ "RepositoryRef",
79
+ "FileChange",
80
+ "IssueState",
81
+ "GitHubIssue",
82
+ "CreateIssueParams",
83
+ "UpdateIssueParams",
84
+ "ListIssuesParams",
85
+ "PullRequestState",
86
+ "GitHubPullRequest",
87
+ "CreatePullRequestParams",
88
+ "UpdatePullRequestParams",
89
+ "ListPullRequestsParams",
90
+ "MergePullRequestParams",
91
+ "ReviewState",
92
+ "GitHubReview",
93
+ "CreateReviewParams",
94
+ "GitHubComment",
95
+ "CreateCommentParams",
96
+ "GitHubBranch",
97
+ "CreateBranchParams",
98
+ "GitHubCommit",
99
+ "CreateCommitParams",
100
+ "GitHubFileContent",
101
+ "GitHubDirectoryEntry",
102
+ "GitHubRepository",
103
+ "GitHubUser",
104
+ "GitHubLabel",
105
+ "GitHubMilestone",
106
+ "GitHubEventType",
107
+ # Service
108
+ "GitHubService",
109
+ ]
110
+
111
+ __version__ = "1.0.0"
112
+ PLUGIN_NAME = "github"
113
+ PLUGIN_DESCRIPTION = "GitHub integration for elizaOS agents"
@@ -0,0 +1,27 @@
1
+ from elizaos_plugin_github.actions.create_branch import CreateBranchAction
2
+ from elizaos_plugin_github.actions.create_comment import CreateCommentAction
3
+ from elizaos_plugin_github.actions.create_issue import CreateIssueAction
4
+ from elizaos_plugin_github.actions.create_pull_request import CreatePullRequestAction
5
+ from elizaos_plugin_github.actions.merge_pull_request import MergePullRequestAction
6
+ from elizaos_plugin_github.actions.push_code import PushCodeAction
7
+ from elizaos_plugin_github.actions.review_pull_request import ReviewPullRequestAction
8
+
9
+ __all__ = [
10
+ "CreateIssueAction",
11
+ "CreatePullRequestAction",
12
+ "ReviewPullRequestAction",
13
+ "CreateCommentAction",
14
+ "CreateBranchAction",
15
+ "PushCodeAction",
16
+ "MergePullRequestAction",
17
+ ]
18
+
19
+ all_actions = [
20
+ CreateIssueAction(),
21
+ CreatePullRequestAction(),
22
+ ReviewPullRequestAction(),
23
+ CreateCommentAction(),
24
+ CreateBranchAction(),
25
+ PushCodeAction(),
26
+ MergePullRequestAction(),
27
+ ]
@@ -0,0 +1,62 @@
1
+ from elizaos_plugin_github.actions.create_issue import ActionContext, ActionResult
2
+ from elizaos_plugin_github.types import CreateBranchParams
3
+
4
+
5
+ class CreateBranchAction:
6
+ @property
7
+ def name(self) -> str:
8
+ return "CREATE_GITHUB_BRANCH"
9
+
10
+ @property
11
+ def description(self) -> str:
12
+ return "Creates a new branch in a GitHub repository from an existing branch or commit."
13
+
14
+ @property
15
+ def similes(self) -> list[str]:
16
+ return [
17
+ "NEW_BRANCH",
18
+ "BRANCH_FROM",
19
+ "FORK_BRANCH",
20
+ "CREATE_FEATURE_BRANCH",
21
+ ]
22
+
23
+ async def validate(self, context: ActionContext) -> bool:
24
+ content = context.message.get("content", {})
25
+ text = ""
26
+ if isinstance(content, dict):
27
+ text = str(content.get("text", "")).lower()
28
+
29
+ return "branch" in text or "fork" in text or "checkout" in text
30
+
31
+ async def handler(
32
+ self,
33
+ context: ActionContext,
34
+ service: object,
35
+ ) -> ActionResult:
36
+ from elizaos_plugin_github.service import GitHubService
37
+
38
+ if not isinstance(service, GitHubService):
39
+ return ActionResult.error_result("GitHub service not available")
40
+
41
+ try:
42
+ branch_name = str(context.message.get("branch_name", "new-branch"))
43
+ from_ref = str(context.message.get("from_ref", "main"))
44
+
45
+ params = CreateBranchParams(
46
+ owner=context.owner,
47
+ repo=context.repo,
48
+ branch_name=branch_name,
49
+ from_ref=from_ref,
50
+ )
51
+
52
+ branch = await service.create_branch(params)
53
+
54
+ return ActionResult.success_result(
55
+ f"Created branch '{branch.name}' from {from_ref}",
56
+ {
57
+ "branch_name": branch.name,
58
+ "sha": branch.sha,
59
+ },
60
+ )
61
+ except Exception as e:
62
+ return ActionResult.error_result(f"Failed to create branch: {e}")
@@ -0,0 +1,67 @@
1
+ from elizaos_plugin_github.actions.create_issue import ActionContext, ActionResult
2
+ from elizaos_plugin_github.types import CreateCommentParams
3
+
4
+
5
+ class CreateCommentAction:
6
+ @property
7
+ def name(self) -> str:
8
+ return "CREATE_GITHUB_COMMENT"
9
+
10
+ @property
11
+ def description(self) -> str:
12
+ return "Creates a comment on a GitHub issue or pull request."
13
+
14
+ @property
15
+ def similes(self) -> list[str]:
16
+ return [
17
+ "COMMENT_ON_ISSUE",
18
+ "COMMENT_ON_PR",
19
+ "ADD_COMMENT",
20
+ "REPLY_TO_ISSUE",
21
+ "POST_COMMENT",
22
+ ]
23
+
24
+ async def validate(self, context: ActionContext) -> bool:
25
+ content = context.message.get("content", {})
26
+ text = ""
27
+ if isinstance(content, dict):
28
+ text = str(content.get("text", "")).lower()
29
+
30
+ return "comment" in text or "reply" in text or "respond" in text
31
+
32
+ async def handler(
33
+ self,
34
+ context: ActionContext,
35
+ service: object,
36
+ ) -> ActionResult:
37
+ from elizaos_plugin_github.service import GitHubService
38
+
39
+ if not isinstance(service, GitHubService):
40
+ return ActionResult.error_result("GitHub service not available")
41
+
42
+ try:
43
+ content = context.message.get("content", {})
44
+ text = ""
45
+ if isinstance(content, dict):
46
+ text = str(content.get("text", ""))
47
+
48
+ issue_number = int(context.message.get("issue_number", 0))
49
+
50
+ params = CreateCommentParams(
51
+ owner=context.owner,
52
+ repo=context.repo,
53
+ issue_number=issue_number,
54
+ body=text,
55
+ )
56
+
57
+ comment = await service.create_comment(params)
58
+
59
+ return ActionResult.success_result(
60
+ f"Added comment to #{issue_number}",
61
+ {
62
+ "comment_id": comment.id,
63
+ "html_url": comment.html_url,
64
+ },
65
+ )
66
+ except Exception as e:
67
+ return ActionResult.error_result(f"Failed to create comment: {e}")
@@ -0,0 +1,93 @@
1
+ from typing import Protocol
2
+
3
+ from elizaos_plugin_github.types import CreateIssueParams
4
+
5
+
6
+ class ActionContext(Protocol):
7
+ message: dict[str, object]
8
+ owner: str
9
+ repo: str
10
+
11
+
12
+ class ActionResult:
13
+ def __init__(
14
+ self,
15
+ success: bool,
16
+ message: str,
17
+ data: dict[str, object] | None = None,
18
+ ) -> None:
19
+ self.success = success
20
+ self.message = message
21
+ self.data = data or {}
22
+
23
+ @classmethod
24
+ def success_result(cls, message: str, data: dict[str, object] | None = None) -> "ActionResult":
25
+ return cls(success=True, message=message, data=data)
26
+
27
+ @classmethod
28
+ def error_result(cls, message: str) -> "ActionResult":
29
+ return cls(success=False, message=message)
30
+
31
+
32
+ class CreateIssueAction:
33
+ @property
34
+ def name(self) -> str:
35
+ return "CREATE_GITHUB_ISSUE"
36
+
37
+ @property
38
+ def description(self) -> str:
39
+ return "Creates a new issue in a GitHub repository. Use this to report bugs, request features, or track tasks."
40
+
41
+ @property
42
+ def similes(self) -> list[str]:
43
+ return [
44
+ "OPEN_ISSUE",
45
+ "NEW_ISSUE",
46
+ "FILE_ISSUE",
47
+ "REPORT_BUG",
48
+ "CREATE_BUG_REPORT",
49
+ "SUBMIT_ISSUE",
50
+ ]
51
+
52
+ async def validate(self, context: ActionContext) -> bool:
53
+ content = context.message.get("content", {})
54
+ text = ""
55
+ if isinstance(content, dict):
56
+ text = str(content.get("text", "")).lower()
57
+
58
+ return "issue" in text or "bug" in text or "report" in text or "ticket" in text
59
+
60
+ async def handler(
61
+ self,
62
+ context: ActionContext,
63
+ service: object,
64
+ ) -> ActionResult:
65
+ from elizaos_plugin_github.service import GitHubService
66
+
67
+ if not isinstance(service, GitHubService):
68
+ return ActionResult.error_result("GitHub service not available")
69
+
70
+ try:
71
+ content = context.message.get("content", {})
72
+ text = ""
73
+ if isinstance(content, dict):
74
+ text = str(content.get("text", ""))
75
+
76
+ params = CreateIssueParams(
77
+ owner=context.owner,
78
+ repo=context.repo,
79
+ title=text[:100] if text else "New Issue",
80
+ body=text,
81
+ )
82
+
83
+ issue = await service.create_issue(params)
84
+
85
+ return ActionResult.success_result(
86
+ f"Created issue #{issue.number}: {issue.title}",
87
+ {
88
+ "issue_number": issue.number,
89
+ "html_url": issue.html_url,
90
+ },
91
+ )
92
+ except Exception as e:
93
+ return ActionResult.error_result(f"Failed to create issue: {e}")
@@ -0,0 +1,73 @@
1
+ from elizaos_plugin_github.actions.create_issue import ActionContext, ActionResult
2
+ from elizaos_plugin_github.types import CreatePullRequestParams
3
+
4
+
5
+ class CreatePullRequestAction:
6
+ @property
7
+ def name(self) -> str:
8
+ return "CREATE_GITHUB_PULL_REQUEST"
9
+
10
+ @property
11
+ def description(self) -> str:
12
+ return "Creates a new pull request in a GitHub repository to merge changes from one branch to another."
13
+
14
+ @property
15
+ def similes(self) -> list[str]:
16
+ return [
17
+ "OPEN_PR",
18
+ "CREATE_PR",
19
+ "NEW_PULL_REQUEST",
20
+ "SUBMIT_PR",
21
+ "OPEN_PULL_REQUEST",
22
+ "MERGE_REQUEST",
23
+ ]
24
+
25
+ async def validate(self, context: ActionContext) -> bool:
26
+ content = context.message.get("content", {})
27
+ text = ""
28
+ if isinstance(content, dict):
29
+ text = str(content.get("text", "")).lower()
30
+
31
+ return "pull request" in text or "pr" in text or "merge" in text
32
+
33
+ async def handler(
34
+ self,
35
+ context: ActionContext,
36
+ service: object,
37
+ ) -> ActionResult:
38
+ from elizaos_plugin_github.service import GitHubService
39
+
40
+ if not isinstance(service, GitHubService):
41
+ return ActionResult.error_result("GitHub service not available")
42
+
43
+ try:
44
+ content = context.message.get("content", {})
45
+ text = ""
46
+ if isinstance(content, dict):
47
+ text = str(content.get("text", ""))
48
+
49
+ head = str(context.message.get("head", "feature"))
50
+ base = str(context.message.get("base", "main"))
51
+
52
+ params = CreatePullRequestParams(
53
+ owner=context.owner,
54
+ repo=context.repo,
55
+ title=text[:100] if text else "New Pull Request",
56
+ body=text,
57
+ head=head,
58
+ base=base,
59
+ )
60
+
61
+ pr = await service.create_pull_request(params)
62
+
63
+ return ActionResult.success_result(
64
+ f"Created pull request #{pr.number}: {pr.title}",
65
+ {
66
+ "pull_number": pr.number,
67
+ "html_url": pr.html_url,
68
+ "head": pr.head.ref,
69
+ "base": pr.base.ref,
70
+ },
71
+ )
72
+ except Exception as e:
73
+ return ActionResult.error_result(f"Failed to create pull request: {e}")
@@ -0,0 +1,82 @@
1
+ from typing import Literal
2
+
3
+ from elizaos_plugin_github.actions.create_issue import ActionContext, ActionResult
4
+ from elizaos_plugin_github.types import MergePullRequestParams
5
+
6
+
7
+ class MergePullRequestAction:
8
+ @property
9
+ def name(self) -> str:
10
+ return "MERGE_GITHUB_PULL_REQUEST"
11
+
12
+ @property
13
+ def description(self) -> str:
14
+ return "Merges a GitHub pull request using merge, squash, or rebase strategy."
15
+
16
+ @property
17
+ def similes(self) -> list[str]:
18
+ return [
19
+ "MERGE_PR",
20
+ "SQUASH_MERGE",
21
+ "REBASE_MERGE",
22
+ "COMPLETE_PR",
23
+ "ACCEPT_PR",
24
+ ]
25
+
26
+ async def validate(self, context: ActionContext) -> bool:
27
+ content = context.message.get("content", {})
28
+ text = ""
29
+ if isinstance(content, dict):
30
+ text = str(content.get("text", "")).lower()
31
+
32
+ return "merge" in text
33
+
34
+ async def handler(
35
+ self,
36
+ context: ActionContext,
37
+ service: object,
38
+ ) -> ActionResult:
39
+ from elizaos_plugin_github.service import GitHubService
40
+
41
+ if not isinstance(service, GitHubService):
42
+ return ActionResult.error_result("GitHub service not available")
43
+
44
+ try:
45
+ content = context.message.get("content", {})
46
+ text = ""
47
+ if isinstance(content, dict):
48
+ text = str(content.get("text", "")).lower()
49
+
50
+ # Determine merge method
51
+ merge_method: Literal["merge", "squash", "rebase"] = "merge"
52
+ if "squash" in text:
53
+ merge_method = "squash"
54
+ elif "rebase" in text:
55
+ merge_method = "rebase"
56
+
57
+ pull_number = int(context.message.get("pull_number", 0))
58
+
59
+ params = MergePullRequestParams(
60
+ owner=context.owner,
61
+ repo=context.repo,
62
+ pull_number=pull_number,
63
+ merge_method=merge_method,
64
+ )
65
+
66
+ sha, merged, message = await service.merge_pull_request(params)
67
+
68
+ if merged:
69
+ return ActionResult.success_result(
70
+ f"Successfully merged pull request #{pull_number}",
71
+ {
72
+ "sha": sha,
73
+ "merged": merged,
74
+ "merge_method": merge_method,
75
+ },
76
+ )
77
+ else:
78
+ return ActionResult.error_result(
79
+ f"Could not merge pull request #{pull_number}: {message}"
80
+ )
81
+ except Exception as e:
82
+ return ActionResult.error_result(f"Failed to merge pull request: {e}")
@@ -0,0 +1,83 @@
1
+ from elizaos_plugin_github.actions.create_issue import ActionContext, ActionResult
2
+ from elizaos_plugin_github.types import CreateCommitParams, FileChange
3
+
4
+
5
+ class PushCodeAction:
6
+ @property
7
+ def name(self) -> str:
8
+ return "PUSH_GITHUB_CODE"
9
+
10
+ @property
11
+ def description(self) -> str:
12
+ return "Creates a commit with file changes and pushes to a GitHub branch."
13
+
14
+ @property
15
+ def similes(self) -> list[str]:
16
+ return [
17
+ "COMMIT_CODE",
18
+ "PUSH_CHANGES",
19
+ "COMMIT_FILES",
20
+ "PUSH_FILES",
21
+ "GIT_PUSH",
22
+ "SAVE_CODE",
23
+ ]
24
+
25
+ async def validate(self, context: ActionContext) -> bool:
26
+ content = context.message.get("content", {})
27
+ text = ""
28
+ if isinstance(content, dict):
29
+ text = str(content.get("text", "")).lower()
30
+
31
+ return "push" in text or "commit" in text or "save" in text or "upload" in text
32
+
33
+ async def handler(
34
+ self,
35
+ context: ActionContext,
36
+ service: object,
37
+ ) -> ActionResult:
38
+ from elizaos_plugin_github.service import GitHubService
39
+
40
+ if not isinstance(service, GitHubService):
41
+ return ActionResult.error_result("GitHub service not available")
42
+
43
+ try:
44
+ content = context.message.get("content", {})
45
+ text = ""
46
+ if isinstance(content, dict):
47
+ text = str(content.get("text", ""))
48
+
49
+ files_data = context.message.get("files", [])
50
+ files: list[FileChange] = []
51
+
52
+ if isinstance(files_data, list):
53
+ for f in files_data:
54
+ if isinstance(f, dict):
55
+ files.append(
56
+ FileChange(
57
+ path=str(f.get("path", "")),
58
+ content=str(f.get("content", "")),
59
+ )
60
+ )
61
+
62
+ branch = str(context.message.get("branch", "main"))
63
+
64
+ params = CreateCommitParams(
65
+ owner=context.owner,
66
+ repo=context.repo,
67
+ message=text[:100] if text else "Update files",
68
+ files=files,
69
+ branch=branch,
70
+ )
71
+
72
+ commit = await service.create_commit(params)
73
+
74
+ return ActionResult.success_result(
75
+ f"Pushed {len(files)} file(s) to {branch}",
76
+ {
77
+ "sha": commit.sha,
78
+ "html_url": commit.html_url,
79
+ "message": commit.message,
80
+ },
81
+ )
82
+ except Exception as e:
83
+ return ActionResult.error_result(f"Failed to push code: {e}")
@@ -0,0 +1,84 @@
1
+ from elizaos_plugin_github.actions.create_issue import ActionContext, ActionResult
2
+ from elizaos_plugin_github.types import CreateReviewParams, ReviewEvent
3
+
4
+
5
+ class ReviewPullRequestAction:
6
+ @property
7
+ def name(self) -> str:
8
+ return "REVIEW_GITHUB_PULL_REQUEST"
9
+
10
+ @property
11
+ def description(self) -> str:
12
+ return "Creates a review on a GitHub pull request. Can approve, request changes, or add comments."
13
+
14
+ @property
15
+ def similes(self) -> list[str]:
16
+ return [
17
+ "APPROVE_PR",
18
+ "REQUEST_CHANGES",
19
+ "COMMENT_ON_PR",
20
+ "REVIEW_PR",
21
+ "PR_REVIEW",
22
+ "CODE_REVIEW",
23
+ ]
24
+
25
+ async def validate(self, context: ActionContext) -> bool:
26
+ content = context.message.get("content", {})
27
+ text = ""
28
+ if isinstance(content, dict):
29
+ text = str(content.get("text", "")).lower()
30
+
31
+ return "review" in text or "approve" in text or "request changes" in text or "lgtm" in text
32
+
33
+ async def handler(
34
+ self,
35
+ context: ActionContext,
36
+ service: object,
37
+ ) -> ActionResult:
38
+ from elizaos_plugin_github.service import GitHubService
39
+
40
+ if not isinstance(service, GitHubService):
41
+ return ActionResult.error_result("GitHub service not available")
42
+
43
+ try:
44
+ content = context.message.get("content", {})
45
+ text = ""
46
+ if isinstance(content, dict):
47
+ text = str(content.get("text", "")).lower()
48
+
49
+ event = ReviewEvent.COMMENT
50
+ if "approve" in text or "lgtm" in text or "looks good" in text:
51
+ event = ReviewEvent.APPROVE
52
+ elif "request changes" in text or "needs work" in text or "fix" in text:
53
+ event = ReviewEvent.REQUEST_CHANGES
54
+
55
+ pull_number = int(context.message.get("pull_number", 0))
56
+
57
+ params = CreateReviewParams(
58
+ owner=context.owner,
59
+ repo=context.repo,
60
+ pull_number=pull_number,
61
+ body=text,
62
+ event=event,
63
+ )
64
+
65
+ review = await service.create_review(params)
66
+
67
+ event_label = (
68
+ "approved"
69
+ if review.state.value == "APPROVED"
70
+ else "requested changes on"
71
+ if review.state.value == "CHANGES_REQUESTED"
72
+ else "commented on"
73
+ )
74
+
75
+ return ActionResult.success_result(
76
+ f"Successfully {event_label} pull request #{pull_number}",
77
+ {
78
+ "review_id": review.id,
79
+ "html_url": review.html_url,
80
+ "state": review.state.value,
81
+ },
82
+ )
83
+ except Exception as e:
84
+ return ActionResult.error_result(f"Failed to create review: {e}")