alita-sdk 0.3.204__py3-none-any.whl → 0.3.206__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.
Files changed (40) hide show
  1. alita_sdk/runtime/clients/client.py +45 -5
  2. alita_sdk/runtime/langchain/assistant.py +22 -21
  3. alita_sdk/runtime/langchain/interfaces/llm_processor.py +1 -4
  4. alita_sdk/runtime/toolkits/application.py +5 -10
  5. alita_sdk/runtime/toolkits/tools.py +0 -1
  6. alita_sdk/runtime/tools/vectorstore.py +157 -13
  7. alita_sdk/runtime/utils/streamlit.py +33 -30
  8. alita_sdk/runtime/utils/utils.py +5 -0
  9. alita_sdk/tools/__init__.py +4 -0
  10. alita_sdk/tools/ado/repos/repos_wrapper.py +20 -13
  11. alita_sdk/tools/aws/__init__.py +7 -0
  12. alita_sdk/tools/aws/delta_lake/__init__.py +136 -0
  13. alita_sdk/tools/aws/delta_lake/api_wrapper.py +220 -0
  14. alita_sdk/tools/aws/delta_lake/schemas.py +20 -0
  15. alita_sdk/tools/aws/delta_lake/tool.py +35 -0
  16. alita_sdk/tools/bitbucket/api_wrapper.py +5 -5
  17. alita_sdk/tools/bitbucket/cloud_api_wrapper.py +54 -29
  18. alita_sdk/tools/elitea_base.py +55 -5
  19. alita_sdk/tools/gitlab/__init__.py +22 -10
  20. alita_sdk/tools/gitlab/api_wrapper.py +278 -253
  21. alita_sdk/tools/gitlab/tools.py +354 -376
  22. alita_sdk/tools/google/__init__.py +7 -0
  23. alita_sdk/tools/google/bigquery/__init__.py +154 -0
  24. alita_sdk/tools/google/bigquery/api_wrapper.py +502 -0
  25. alita_sdk/tools/google/bigquery/schemas.py +102 -0
  26. alita_sdk/tools/google/bigquery/tool.py +34 -0
  27. alita_sdk/tools/llm/llm_utils.py +0 -6
  28. alita_sdk/tools/openapi/__init__.py +14 -3
  29. alita_sdk/tools/sharepoint/__init__.py +2 -1
  30. alita_sdk/tools/sharepoint/api_wrapper.py +71 -7
  31. alita_sdk/tools/testrail/__init__.py +9 -1
  32. alita_sdk/tools/testrail/api_wrapper.py +154 -5
  33. alita_sdk/tools/utils/content_parser.py +77 -13
  34. alita_sdk/tools/zephyr_scale/api_wrapper.py +271 -22
  35. {alita_sdk-0.3.204.dist-info → alita_sdk-0.3.206.dist-info}/METADATA +3 -1
  36. {alita_sdk-0.3.204.dist-info → alita_sdk-0.3.206.dist-info}/RECORD +39 -30
  37. alita_sdk/runtime/llms/alita.py +0 -259
  38. {alita_sdk-0.3.204.dist-info → alita_sdk-0.3.206.dist-info}/WHEEL +0 -0
  39. {alita_sdk-0.3.204.dist-info → alita_sdk-0.3.206.dist-info}/licenses/LICENSE +0 -0
  40. {alita_sdk-0.3.204.dist-info → alita_sdk-0.3.206.dist-info}/top_level.txt +0 -0
@@ -1,42 +1,124 @@
1
- """Util that calls gitlab."""
2
- from __future__ import annotations
3
-
4
- import json
5
- from datetime import datetime
6
- from langchain_core.tools import ToolException
7
- from typing import TYPE_CHECKING, Any, Dict, List, Optional
8
-
9
- from pydantic import BaseModel, model_validator, SecretStr
10
- from pydantic.fields import PrivateAttr
11
-
12
- if TYPE_CHECKING:
13
- from gitlab.v4.objects import Issue
14
-
15
-
16
- class GitLabAPIWrapper(BaseModel):
17
- """Wrapper for GitLab API."""
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 validate_env(cls, values: Dict) -> Dict:
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
- def set_active_branch(self, branch: str) -> None:
60
- """Set the active branch for the bot."""
61
- self._active_branch = branch
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 json.dumps([branch.name for branch in branches])
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 f"Files: {paths}"
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 f"Folders: {paths}"
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
- def create_branch(self, branch_name: str) -> None:
91
- """Create a new branch in the repository."""
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[Issue]) -> List[dict]:
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
- self._repo_instance.files.delete(
367
- file_path, branch, "Delete " + file_path
368
- )
369
- return "Deleted file " + file_path
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" + str(e)
372
-
373
- def extract_old_new_pairs(self, file_query):
374
- # Split the file content by lines
375
- code_lines = file_query.split("\n")
376
-
377
- # Initialize lists to hold the contents of OLD and NEW sections
378
- old_contents = []
379
- new_contents = []
380
-
381
- # Initialize variables to track whether the current line is within an OLD or NEW section
382
- in_old_section = False
383
- in_new_section = False
384
-
385
- # Temporary storage for the current section's content
386
- current_section_content = []
387
-
388
- # Iterate through each line in the file content
389
- for line in code_lines:
390
- # Check for OLD section start
391
- if "OLD <<<" in line:
392
- in_old_section = True
393
- current_section_content = [] # Reset current section content
394
- continue # Skip the line with the marker
395
-
396
- # Check for OLD section end
397
- if ">>>> OLD" in line:
398
- in_old_section = False
399
- old_contents.append("\n".join(current_section_content).strip()) # Add the captured content
400
- current_section_content = [] # Reset current section content
401
- continue # Skip the line with the marker
402
-
403
- # Check for NEW section start
404
- if "NEW <<<" in line:
405
- in_new_section = True
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
- # Remove None values from the parameters
457
- params = {key: value for key, value in params.items() if value is not None}
458
-
459
- # Call the GitHub API to get commits
460
- commits = self._repo_instance.commits.list(**params)
461
-
462
- # Convert the commits to a list of dictionaries for easier processing
463
- commit_list = [
464
- {
465
- "sha": commit.id,
466
- "author": commit.author_name,
467
- "createdAt": commit.created_at,
468
- "message": commit.message,
469
- "url": commit.web_url,
470
- }
471
- for commit in commits
472
- ]
473
-
474
- return commit_list
475
- except Exception as e:
476
- return ToolException(f"Unable to retrieve commits due to error:\n{str(e)}")
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()