alita-sdk 0.3.205__py3-none-any.whl → 0.3.207__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.
- alita_sdk/runtime/clients/client.py +314 -11
- alita_sdk/runtime/langchain/assistant.py +22 -21
- alita_sdk/runtime/langchain/interfaces/llm_processor.py +1 -4
- alita_sdk/runtime/langchain/langraph_agent.py +6 -1
- alita_sdk/runtime/langchain/store_manager.py +4 -4
- alita_sdk/runtime/toolkits/application.py +5 -10
- alita_sdk/runtime/toolkits/tools.py +11 -21
- alita_sdk/runtime/tools/vectorstore.py +25 -11
- alita_sdk/runtime/utils/streamlit.py +505 -222
- alita_sdk/runtime/utils/toolkit_runtime.py +147 -0
- alita_sdk/runtime/utils/toolkit_utils.py +157 -0
- alita_sdk/runtime/utils/utils.py +5 -0
- alita_sdk/tools/__init__.py +2 -0
- alita_sdk/tools/ado/repos/repos_wrapper.py +20 -13
- alita_sdk/tools/bitbucket/api_wrapper.py +5 -5
- alita_sdk/tools/bitbucket/cloud_api_wrapper.py +54 -29
- alita_sdk/tools/elitea_base.py +9 -4
- alita_sdk/tools/gitlab/__init__.py +22 -10
- alita_sdk/tools/gitlab/api_wrapper.py +278 -253
- alita_sdk/tools/gitlab/tools.py +354 -376
- alita_sdk/tools/llm/llm_utils.py +0 -6
- alita_sdk/tools/memory/__init__.py +54 -10
- alita_sdk/tools/openapi/__init__.py +14 -3
- alita_sdk/tools/sharepoint/__init__.py +2 -1
- alita_sdk/tools/sharepoint/api_wrapper.py +11 -3
- alita_sdk/tools/testrail/api_wrapper.py +39 -16
- alita_sdk/tools/utils/content_parser.py +77 -13
- {alita_sdk-0.3.205.dist-info → alita_sdk-0.3.207.dist-info}/METADATA +1 -1
- {alita_sdk-0.3.205.dist-info → alita_sdk-0.3.207.dist-info}/RECORD +32 -40
- alita_sdk/community/analysis/__init__.py +0 -0
- alita_sdk/community/analysis/ado_analyse/__init__.py +0 -103
- alita_sdk/community/analysis/ado_analyse/api_wrapper.py +0 -261
- alita_sdk/community/analysis/github_analyse/__init__.py +0 -98
- alita_sdk/community/analysis/github_analyse/api_wrapper.py +0 -166
- alita_sdk/community/analysis/gitlab_analyse/__init__.py +0 -110
- alita_sdk/community/analysis/gitlab_analyse/api_wrapper.py +0 -172
- alita_sdk/community/analysis/jira_analyse/__init__.py +0 -141
- alita_sdk/community/analysis/jira_analyse/api_wrapper.py +0 -252
- alita_sdk/runtime/llms/alita.py +0 -259
- {alita_sdk-0.3.205.dist-info → alita_sdk-0.3.207.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.205.dist-info → alita_sdk-0.3.207.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.205.dist-info → alita_sdk-0.3.207.dist-info}/top_level.txt +0 -0
@@ -1,42 +1,124 @@
|
|
1
|
-
|
2
|
-
from
|
3
|
-
|
4
|
-
import
|
5
|
-
from
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
"
|
18
|
-
|
1
|
+
# api_wrapper.py
|
2
|
+
from typing import Any, Dict, List, Optional
|
3
|
+
|
4
|
+
from alita_sdk.tools.elitea_base import BaseCodeToolApiWrapper
|
5
|
+
from pydantic import create_model, Field, model_validator, SecretStr, PrivateAttr
|
6
|
+
|
7
|
+
AppendFileModel = create_model(
|
8
|
+
"AppendFileModel",
|
9
|
+
file_path=(str, Field(description="The path of the file")),
|
10
|
+
content=(str, Field(description="The content to append to the file")),
|
11
|
+
branch=(str, Field(description="The branch to append the file in")),
|
12
|
+
)
|
13
|
+
DeleteFileModel = create_model(
|
14
|
+
"DeleteFileModel",
|
15
|
+
file_path=(str, Field(description="The path of the file")),
|
16
|
+
branch=(str, Field(description="The branch to delete the file from")),
|
17
|
+
commit_message=(str, Field(default=None, description="Commit message for deleting the file. Optional.")),
|
18
|
+
)
|
19
|
+
CreateFileModel = create_model(
|
20
|
+
"CreateFileModel",
|
21
|
+
file_path=(str, Field(description="The path of the file")),
|
22
|
+
file_contents=(str, Field(description="The contents of the file")),
|
23
|
+
branch=(str, Field(description="The branch to create the file in")),
|
24
|
+
)
|
25
|
+
ReadFileModel = create_model(
|
26
|
+
"ReadFileModel",
|
27
|
+
file_path=(str, Field(description="The path of the file")),
|
28
|
+
branch=(str, Field(description="The branch to read the file from")),
|
29
|
+
)
|
30
|
+
UpdateFileModel = create_model(
|
31
|
+
"UpdateFileModel",
|
32
|
+
file_query=(str, Field(description="The file query string")),
|
33
|
+
branch=(str, Field(description="The branch to update the file in")),
|
34
|
+
)
|
35
|
+
CommentOnIssueModel = create_model(
|
36
|
+
"CommentOnIssueModel",
|
37
|
+
comment_query=(str, Field(description="The comment query string")),
|
38
|
+
)
|
39
|
+
GetIssueModel = create_model(
|
40
|
+
"GetIssueModel",
|
41
|
+
issue_number=(int, Field(description="The number of the issue")),
|
42
|
+
)
|
43
|
+
CreatePullRequestModel = create_model(
|
44
|
+
"CreatePullRequestModel",
|
45
|
+
pr_title=(str, Field(description="The title of the pull request")),
|
46
|
+
pr_body=(str, Field(description="The body of the pull request")),
|
47
|
+
branch=(str, Field(description="The branch to create the pull request from")),
|
48
|
+
)
|
49
|
+
|
50
|
+
CreateBranchModel = create_model(
|
51
|
+
"CreateBranchModel",
|
52
|
+
branch_name=(str, Field(description="The name of the branch, e.g. `my_branch`.")),
|
53
|
+
)
|
54
|
+
ListBranchesInRepoModel = create_model(
|
55
|
+
"ListBranchesInRepoModel",
|
56
|
+
)
|
57
|
+
ListFilesModel = create_model(
|
58
|
+
"ListFilesModel",
|
59
|
+
path=(Optional[str], Field(description="The path to list files from")),
|
60
|
+
recursive=(bool, Field(description="Whether to list files recursively", default=True)),
|
61
|
+
branch=(Optional[str], Field(description="The branch to list files from")),
|
62
|
+
)
|
63
|
+
ListFoldersModel = create_model(
|
64
|
+
"ListFoldersModel",
|
65
|
+
path=(Optional[str], Field(description="The path to list folders from")),
|
66
|
+
recursive=(bool, Field(description="Whether to list folders recursively", default=True)),
|
67
|
+
branch=(Optional[str], Field(description="The branch to list folders from")),
|
68
|
+
)
|
69
|
+
GetIssuesModel = create_model(
|
70
|
+
"GetIssuesModel",
|
71
|
+
)
|
72
|
+
SetActiveBranchModel = create_model(
|
73
|
+
"SetActiveBranchModel",
|
74
|
+
branch_name=(str, Field(description="The name of the branch, e.g. `my_branch`.")),
|
75
|
+
)
|
76
|
+
GetPRChangesModel = create_model(
|
77
|
+
"GetPRChangesModel",
|
78
|
+
pr_number=(int, Field(description="GitLab Merge Request (Pull Request) number")),
|
79
|
+
)
|
80
|
+
CreatePRChangeCommentModel = create_model(
|
81
|
+
"CreatePRChangeCommentModel",
|
82
|
+
pr_number=(int, Field(description="GitLab Merge Request (Pull Request) number")),
|
83
|
+
file_path=(str, Field(description="File path of the changed file")),
|
84
|
+
line_number=(int, Field(description="Line number from the diff for a changed file")),
|
85
|
+
comment=(str, Field(description="Comment content")),
|
86
|
+
)
|
87
|
+
GetCommitsModel = create_model(
|
88
|
+
"GetCommitsModel",
|
89
|
+
sha=(Optional[str], Field(description="Commit SHA", default=None)),
|
90
|
+
path=(Optional[str], Field(description="File path", default=None)),
|
91
|
+
since=(Optional[str], Field(description="Start date", default=None)),
|
92
|
+
until=(Optional[str], Field(description="End date", default=None)),
|
93
|
+
author=(Optional[str], Field(description="Author name", default=None)),
|
94
|
+
)
|
95
|
+
|
96
|
+
class GitLabAPIWrapper(BaseCodeToolApiWrapper):
|
97
|
+
url: str
|
98
|
+
repository: str
|
99
|
+
private_token: SecretStr
|
100
|
+
branch: Optional[str] = 'main'
|
19
101
|
_git: Any = PrivateAttr()
|
20
102
|
_repo_instance: Any = PrivateAttr()
|
21
103
|
_active_branch: Any = PrivateAttr()
|
22
|
-
url: str = ''
|
23
|
-
repository: str = ''
|
24
|
-
"""The name of the GitLab repository, in the form {username}/{repo-name}."""
|
25
|
-
private_token: SecretStr = None
|
26
|
-
"""Personal access token for the GitLab service, used for authentication."""
|
27
|
-
branch: Optional[str] = 'main'
|
28
|
-
"""The specific branch in the GitLab repository where the bot will make
|
29
|
-
its commits. Defaults to 'main'.
|
30
|
-
"""
|
31
104
|
|
105
|
+
llm: Optional[Any] = None
|
106
|
+
# Alita instance
|
107
|
+
alita: Optional[Any] = None
|
108
|
+
|
109
|
+
# Vector store configuration
|
110
|
+
connection_string: Optional[SecretStr] = None
|
111
|
+
collection_name: Optional[str] = None
|
112
|
+
doctype: Optional[str] = 'code'
|
113
|
+
embedding_model: Optional[str] = "HuggingFaceEmbeddings"
|
114
|
+
embedding_model_params: Optional[Dict[str, Any]] = {"model_name": "sentence-transformers/all-MiniLM-L6-v2"}
|
115
|
+
vectorstore_type: Optional[str] = "PGVector"
|
32
116
|
|
33
117
|
@model_validator(mode='before')
|
34
118
|
@classmethod
|
35
|
-
def
|
36
|
-
"""Validate that api key and python package exists in environment."""
|
119
|
+
def validate_toolkit(cls, values: Dict) -> Dict:
|
37
120
|
try:
|
38
121
|
import gitlab
|
39
|
-
|
40
122
|
except ImportError:
|
41
123
|
raise ImportError(
|
42
124
|
"python-gitlab is not installed. "
|
@@ -55,40 +137,40 @@ class GitLabAPIWrapper(BaseModel):
|
|
55
137
|
cls._active_branch = values.get('branch')
|
56
138
|
return values
|
57
139
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
self._repo_instance.default_branch = branch
|
63
|
-
return f"Active branch set to {branch}"
|
64
|
-
|
140
|
+
def set_active_branch(self, branch_name: str) -> str:
|
141
|
+
self._active_branch = branch_name
|
142
|
+
self._repo_instance.default_branch = branch_name
|
143
|
+
return f"Active branch set to {branch_name}"
|
65
144
|
|
66
145
|
def list_branches_in_repo(self) -> List[str]:
|
67
|
-
"""List all branches in the repository."""
|
68
146
|
branches = self._repo_instance.branches.list()
|
69
|
-
return
|
147
|
+
return [branch.name for branch in branches]
|
70
148
|
|
71
149
|
def list_files(self, path: str = None, recursive: bool = True, branch: str = None) -> List[str]:
|
72
|
-
"""List files by defined path."""
|
73
150
|
branch = branch if branch else self._active_branch
|
74
151
|
files = self._get_all_files(path, recursive, branch)
|
75
152
|
paths = [file['path'] for file in files if file['type'] == 'blob']
|
76
|
-
return
|
153
|
+
return paths
|
77
154
|
|
78
155
|
def list_folders(self, path: str = None, recursive: bool = True, branch: str = None) -> List[str]:
|
79
|
-
"""List folders by defined path."""
|
80
156
|
branch = branch if branch else self._active_branch
|
81
157
|
files = self._get_all_files(path, recursive, branch)
|
82
158
|
paths = [file['path'] for file in files if file['type'] == 'tree']
|
83
|
-
return
|
159
|
+
return paths
|
84
160
|
|
85
161
|
def _get_all_files(self, path: str = None, recursive: bool = True, branch: str = None):
|
86
162
|
branch = branch if branch else self._active_branch
|
87
|
-
return self._repo_instance.repository_tree(path=path, ref=branch,
|
88
|
-
recursive=recursive, all=True)
|
163
|
+
return self._repo_instance.repository_tree(path=path, ref=branch, recursive=recursive, all=True)
|
89
164
|
|
90
|
-
|
91
|
-
|
165
|
+
# overrided for indexer
|
166
|
+
def _get_files(self, path: str = None, recursive: bool = True, branch: str = None):
|
167
|
+
gitlab_files = self._get_all_files(path, recursive, branch)
|
168
|
+
return [file['path'] for file in gitlab_files if file['type'] == 'blob']
|
169
|
+
|
170
|
+
def _read_file(self, file_path: str, branch: str):
|
171
|
+
return self.read_file(file_path, branch)
|
172
|
+
|
173
|
+
def create_branch(self, branch_name: str) -> str:
|
92
174
|
try:
|
93
175
|
self._repo_instance.branches.create(
|
94
176
|
{
|
@@ -104,14 +186,7 @@ class GitLabAPIWrapper(BaseModel):
|
|
104
186
|
self._active_branch = branch_name
|
105
187
|
return f"Branch {branch_name} created successfully and set as active"
|
106
188
|
|
107
|
-
def parse_issues(self, issues: List[
|
108
|
-
"""
|
109
|
-
Extracts title and number from each Issue and puts them in a dictionary
|
110
|
-
Parameters:
|
111
|
-
issues(List[Issue]): A list of gitlab Issue objects
|
112
|
-
Returns:
|
113
|
-
List[dict]: A dictionary of issue titles and numbers
|
114
|
-
"""
|
189
|
+
def parse_issues(self, issues: List[Any]) -> List[dict]:
|
115
190
|
parsed = []
|
116
191
|
for issue in issues:
|
117
192
|
title = issue.title
|
@@ -120,13 +195,6 @@ class GitLabAPIWrapper(BaseModel):
|
|
120
195
|
return parsed
|
121
196
|
|
122
197
|
def get_issues(self) -> str:
|
123
|
-
"""
|
124
|
-
Fetches all open issues from the repo
|
125
|
-
|
126
|
-
Returns:
|
127
|
-
str: A plaintext report containing the number of issues
|
128
|
-
and each issue's title and number.
|
129
|
-
"""
|
130
198
|
issues = self._repo_instance.issues.list(state="opened")
|
131
199
|
if len(issues) > 0:
|
132
200
|
parsed_issues = self.parse_issues(issues)
|
@@ -138,14 +206,6 @@ class GitLabAPIWrapper(BaseModel):
|
|
138
206
|
return "No open issues available"
|
139
207
|
|
140
208
|
def get_issue(self, issue_number: int) -> Dict[str, Any]:
|
141
|
-
"""
|
142
|
-
Fetches a specific issue and its first 10 comments
|
143
|
-
Parameters:
|
144
|
-
issue_number(int): The number for the gitlab issue
|
145
|
-
Returns:
|
146
|
-
dict: A dictionary containing the issue's title,
|
147
|
-
body, and comments as a string
|
148
|
-
"""
|
149
209
|
issue = self._repo_instance.issues.get(issue_number)
|
150
210
|
page = 0
|
151
211
|
comments: List[dict] = []
|
@@ -167,16 +227,6 @@ class GitLabAPIWrapper(BaseModel):
|
|
167
227
|
}
|
168
228
|
|
169
229
|
def create_pull_request(self, pr_title: str, pr_body: str, branch: str) -> str:
|
170
|
-
"""
|
171
|
-
Makes a pull request from the bot's branch to the base branch
|
172
|
-
Parameters:
|
173
|
-
pr_query(str): a string which contains the PR title
|
174
|
-
and the PR body. The title is the first line
|
175
|
-
in the string, and the body are the rest of the string.
|
176
|
-
For example, "Updated README\nmade changes to add info"
|
177
|
-
Returns:
|
178
|
-
str: A success or failure message
|
179
|
-
"""
|
180
230
|
if self.branch == branch:
|
181
231
|
return f"""Cannot make a pull request because
|
182
232
|
commits are already in the {self.branch} branch"""
|
@@ -196,16 +246,6 @@ class GitLabAPIWrapper(BaseModel):
|
|
196
246
|
return "Unable to make pull request due to error:\n" + str(e)
|
197
247
|
|
198
248
|
def comment_on_issue(self, comment_query: str) -> str:
|
199
|
-
"""
|
200
|
-
Adds a comment to a gitlab issue
|
201
|
-
Parameters:
|
202
|
-
comment_query(str): a string which contains the issue number,
|
203
|
-
two newlines, and the comment.
|
204
|
-
for example: "1\n\nWorking on it now"
|
205
|
-
adds the comment "working on it now" to issue 1
|
206
|
-
Returns:
|
207
|
-
str: A success or failure message
|
208
|
-
"""
|
209
249
|
issue_number = int(comment_query.split("\n\n")[0])
|
210
250
|
comment = comment_query[len(str(issue_number)) + 2 :]
|
211
251
|
try:
|
@@ -215,18 +255,7 @@ class GitLabAPIWrapper(BaseModel):
|
|
215
255
|
except Exception as e:
|
216
256
|
return "Unable to make comment due to error:\n" + str(e)
|
217
257
|
|
218
|
-
|
219
258
|
def create_file(self, file_path: str, file_contents: str, branch: str) -> str:
|
220
|
-
"""
|
221
|
-
Creates a new file on the gitlab repo
|
222
|
-
Parameters:
|
223
|
-
file_query(str): a string which contains the file path
|
224
|
-
and the file contents. The file path is the first line
|
225
|
-
in the string, and the contents are the rest of the string.
|
226
|
-
For example, "hello_world.md\n# Hello World!"
|
227
|
-
Returns:
|
228
|
-
str: A success or failure message
|
229
|
-
"""
|
230
259
|
try:
|
231
260
|
self.set_active_branch(branch)
|
232
261
|
self._repo_instance.files.get(file_path, branch)
|
@@ -243,35 +272,11 @@ class GitLabAPIWrapper(BaseModel):
|
|
243
272
|
return "Created file " + file_path
|
244
273
|
|
245
274
|
def read_file(self, file_path: str, branch: str) -> str:
|
246
|
-
"""
|
247
|
-
Reads a file from the gitlab repo
|
248
|
-
Parameters:
|
249
|
-
file_path(str): the file path
|
250
|
-
Returns:
|
251
|
-
str: The file decoded as a string
|
252
|
-
"""
|
253
275
|
self.set_active_branch(branch)
|
254
276
|
file = self._repo_instance.files.get(file_path, branch)
|
255
277
|
return file.decode().decode("utf-8")
|
256
278
|
|
257
279
|
def update_file(self, file_query: str, branch: str) -> str:
|
258
|
-
"""
|
259
|
-
Updates a file with new content.
|
260
|
-
Parameters:
|
261
|
-
file_query(str): Contains the file path and the file contents.
|
262
|
-
The old file contents is wrapped in OLD <<<< and >>>> OLD
|
263
|
-
The new file contents is wrapped in NEW <<<< and >>>> NEW
|
264
|
-
For example:
|
265
|
-
/test/hello.txt
|
266
|
-
OLD <<<<
|
267
|
-
Hello Earth!
|
268
|
-
>>>> OLD
|
269
|
-
NEW <<<<
|
270
|
-
Hello Mars!
|
271
|
-
>>>> NEW
|
272
|
-
Returns:
|
273
|
-
A success or failure message
|
274
|
-
"""
|
275
280
|
if branch == self.branch:
|
276
281
|
return (
|
277
282
|
"You're attempting to commit to the directly"
|
@@ -313,16 +318,6 @@ class GitLabAPIWrapper(BaseModel):
|
|
313
318
|
return "Unable to update file due to error:\n" + str(e)
|
314
319
|
|
315
320
|
def append_file(self, file_path: str, content: str, branch: str) -> str:
|
316
|
-
"""
|
317
|
-
Appends new content to the end of file.
|
318
|
-
Parameters:
|
319
|
-
file_path(str): Contains the file path.
|
320
|
-
For example:
|
321
|
-
/test/hello.txt
|
322
|
-
content(str): new content.
|
323
|
-
Returns:
|
324
|
-
A success or failure message
|
325
|
-
"""
|
326
321
|
if branch == self.branch:
|
327
322
|
return (
|
328
323
|
"You're attempting to commit to the directly"
|
@@ -352,125 +347,155 @@ class GitLabAPIWrapper(BaseModel):
|
|
352
347
|
except Exception as e:
|
353
348
|
return "Unable to update file due to error:\n" + str(e)
|
354
349
|
|
355
|
-
|
356
|
-
def delete_file(self, file_path: str, branch: str) -> str:
|
357
|
-
"""
|
358
|
-
Deletes a file from the repo
|
359
|
-
Parameters:
|
360
|
-
file_path(str): Where the file is
|
361
|
-
Returns:
|
362
|
-
str: Success or failure message
|
363
|
-
"""
|
350
|
+
def delete_file(self, file_path: str, branch: str, commit_message: str = None) -> str:
|
364
351
|
try:
|
365
352
|
self.set_active_branch(branch)
|
366
|
-
|
367
|
-
|
368
|
-
)
|
369
|
-
return "Deleted file "
|
353
|
+
if not commit_message:
|
354
|
+
commit_message = f"Delete {file_path}"
|
355
|
+
self._repo_instance.files.delete(file_path, branch, commit_message)
|
356
|
+
return f"Deleted file {file_path}"
|
370
357
|
except Exception as e:
|
371
|
-
return "Unable to delete file due to error:\n"
|
372
|
-
|
373
|
-
def
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
current_section_content = [] # Reset current section content
|
407
|
-
continue # Skip the line with the marker
|
408
|
-
|
409
|
-
# Check for NEW section end
|
410
|
-
if ">>>> NEW" in line:
|
411
|
-
in_new_section = False
|
412
|
-
new_contents.append("\n".join(current_section_content).strip()) # Add the captured content
|
413
|
-
current_section_content = [] # Reset current section content
|
414
|
-
continue # Skip the line with the marker
|
415
|
-
|
416
|
-
# If currently in an OLD or NEW section, add the line to the current section content
|
417
|
-
if in_old_section or in_new_section:
|
418
|
-
current_section_content.append(line)
|
419
|
-
|
420
|
-
# Pair the OLD and NEW contents
|
421
|
-
paired_contents = list(zip(old_contents, new_contents))
|
422
|
-
|
423
|
-
return paired_contents
|
424
|
-
|
425
|
-
def get_commits(
|
426
|
-
self,
|
427
|
-
sha: Optional[str] = None,
|
428
|
-
path: Optional[str] = None,
|
429
|
-
since: Optional[str] = None,
|
430
|
-
until: Optional[str] = None,
|
431
|
-
author: Optional[str] = None,
|
432
|
-
) -> str:
|
433
|
-
"""
|
434
|
-
Retrieves a list of commits from the repository.
|
435
|
-
|
436
|
-
Parameters:
|
437
|
-
sha (Optional[str]): The commit SHA to start listing commits from.
|
438
|
-
path (Optional[str]): The file path to filter commits by.
|
439
|
-
since (Optional[datetime]): Only commits after this date will be returned.
|
440
|
-
until (Optional[datetime]): Only commits before this date will be returned.
|
441
|
-
author (Optional[str]): The author of the commits.
|
442
|
-
|
443
|
-
Returns:
|
444
|
-
str: A list of commit data or an error message.
|
445
|
-
"""
|
446
|
-
try:
|
447
|
-
# Prepare the parameters for the API call
|
448
|
-
params = {
|
449
|
-
"ref_name": sha,
|
450
|
-
"path": path,
|
451
|
-
"since": datetime.fromisoformat(since) if since else None,
|
452
|
-
"until": datetime.fromisoformat(until) if until else None,
|
453
|
-
"author": author if isinstance(author, str) else None,
|
454
|
-
"all" : True
|
358
|
+
return f"Unable to delete file due to error:\n{e}"
|
359
|
+
|
360
|
+
def get_pr_changes(self, pr_number: int) -> str:
|
361
|
+
mr = self._repo_instance.mergerequests.get(pr_number)
|
362
|
+
res = f"title: {mr.title}\ndescription: {mr.description}\n\n"
|
363
|
+
for change in mr.changes()["changes"]:
|
364
|
+
res += f"diff --git a/{change['old_path']} b/{change['new_path']}\n{change['diff']}\n"
|
365
|
+
return res
|
366
|
+
|
367
|
+
def create_pr_change_comment(self, pr_number: int, file_path: str, line_number: int, comment: str) -> str:
|
368
|
+
mr = self._repo_instance.mergerequests.get(pr_number)
|
369
|
+
position = {"position_type": "text", "new_path": file_path, "new_line": line_number}
|
370
|
+
mr.discussions.create({"body": comment, "position": position})
|
371
|
+
return "Comment added"
|
372
|
+
|
373
|
+
def get_commits(self, sha: Optional[str] = None, path: Optional[str] = None, since: Optional[str] = None, until: Optional[str] = None, author: Optional[str] = None):
|
374
|
+
params = {}
|
375
|
+
if sha:
|
376
|
+
params["ref_name"] = sha
|
377
|
+
if path:
|
378
|
+
params["path"] = path
|
379
|
+
if since:
|
380
|
+
params["since"] = since
|
381
|
+
if until:
|
382
|
+
params["until"] = until
|
383
|
+
if author:
|
384
|
+
params["author"] = author
|
385
|
+
commits = self._repo_instance.commits.list(**params)
|
386
|
+
return [
|
387
|
+
{
|
388
|
+
"sha": commit.id,
|
389
|
+
"author": commit.author_name,
|
390
|
+
"createdAt": commit.created_at,
|
391
|
+
"message": commit.message,
|
392
|
+
"url": commit.web_url,
|
455
393
|
}
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
394
|
+
for commit in commits
|
395
|
+
]
|
396
|
+
|
397
|
+
def get_available_tools(self):
|
398
|
+
return [
|
399
|
+
{
|
400
|
+
"name": "create_branch",
|
401
|
+
"ref": self.create_branch,
|
402
|
+
"description": self.create_branch.__doc__,
|
403
|
+
"args_schema": CreateBranchModel,
|
404
|
+
},
|
405
|
+
{
|
406
|
+
"name": "list_branches_in_repo",
|
407
|
+
"ref": self.list_branches_in_repo,
|
408
|
+
"description": self.list_branches_in_repo.__doc__,
|
409
|
+
"args_schema": ListBranchesInRepoModel,
|
410
|
+
},
|
411
|
+
{
|
412
|
+
"name": "list_files",
|
413
|
+
"ref": self.list_files,
|
414
|
+
"description": self.list_files.__doc__,
|
415
|
+
"args_schema": ListFilesModel,
|
416
|
+
},
|
417
|
+
{
|
418
|
+
"name": "list_folders",
|
419
|
+
"ref": self.list_folders,
|
420
|
+
"description": self.list_folders.__doc__,
|
421
|
+
"args_schema": ListFoldersModel,
|
422
|
+
},
|
423
|
+
{
|
424
|
+
"name": "get_issues",
|
425
|
+
"ref": self.get_issues,
|
426
|
+
"description": self.get_issues.__doc__,
|
427
|
+
"args_schema": GetIssuesModel,
|
428
|
+
},
|
429
|
+
{
|
430
|
+
"name": "get_issue",
|
431
|
+
"ref": self.get_issue,
|
432
|
+
"description": self.get_issue.__doc__,
|
433
|
+
"args_schema": GetIssueModel,
|
434
|
+
},
|
435
|
+
{
|
436
|
+
"name": "create_pull_request",
|
437
|
+
"ref": self.create_pull_request,
|
438
|
+
"description": self.create_pull_request.__doc__,
|
439
|
+
"args_schema": CreatePullRequestModel,
|
440
|
+
},
|
441
|
+
{
|
442
|
+
"name": "comment_on_issue",
|
443
|
+
"ref": self.comment_on_issue,
|
444
|
+
"description": self.comment_on_issue.__doc__,
|
445
|
+
"args_schema": CommentOnIssueModel,
|
446
|
+
},
|
447
|
+
{
|
448
|
+
"name": "create_file",
|
449
|
+
"ref": self.create_file,
|
450
|
+
"description": self.create_file.__doc__,
|
451
|
+
"args_schema": CreateFileModel,
|
452
|
+
},
|
453
|
+
{
|
454
|
+
"name": "read_file",
|
455
|
+
"ref": self.read_file,
|
456
|
+
"description": self.read_file.__doc__,
|
457
|
+
"args_schema": ReadFileModel,
|
458
|
+
},
|
459
|
+
{
|
460
|
+
"name": "update_file",
|
461
|
+
"ref": self.update_file,
|
462
|
+
"description": self.update_file.__doc__,
|
463
|
+
"args_schema": UpdateFileModel,
|
464
|
+
},
|
465
|
+
{
|
466
|
+
"name": "append_file",
|
467
|
+
"ref": self.append_file,
|
468
|
+
"description": self.append_file.__doc__,
|
469
|
+
"args_schema": AppendFileModel,
|
470
|
+
},
|
471
|
+
{
|
472
|
+
"name": "delete_file",
|
473
|
+
"ref": self.delete_file,
|
474
|
+
"description": self.delete_file.__doc__,
|
475
|
+
"args_schema": DeleteFileModel,
|
476
|
+
},
|
477
|
+
{
|
478
|
+
"name": "set_active_branch",
|
479
|
+
"ref": self.set_active_branch,
|
480
|
+
"description": "Set the active branch in the repository.",
|
481
|
+
"args_schema": SetActiveBranchModel,
|
482
|
+
},
|
483
|
+
{
|
484
|
+
"name": "get_pr_changes",
|
485
|
+
"ref": self.get_pr_changes,
|
486
|
+
"description": "Get all changes from a pull request in git diff format.",
|
487
|
+
"args_schema": GetPRChangesModel,
|
488
|
+
},
|
489
|
+
{
|
490
|
+
"name": "create_pr_change_comment",
|
491
|
+
"ref": self.create_pr_change_comment,
|
492
|
+
"description": "Create a comment on a pull request change.",
|
493
|
+
"args_schema": CreatePRChangeCommentModel,
|
494
|
+
},
|
495
|
+
{
|
496
|
+
"name": "get_commits",
|
497
|
+
"ref": self.get_commits,
|
498
|
+
"description": "Retrieve a list of commits from the repository.",
|
499
|
+
"args_schema": GetCommitsModel,
|
500
|
+
},
|
501
|
+
] + self._get_vector_search_tools()
|