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.
- alita_sdk/runtime/clients/client.py +45 -5
- alita_sdk/runtime/langchain/assistant.py +22 -21
- alita_sdk/runtime/langchain/interfaces/llm_processor.py +1 -4
- alita_sdk/runtime/toolkits/application.py +5 -10
- alita_sdk/runtime/toolkits/tools.py +0 -1
- alita_sdk/runtime/tools/vectorstore.py +157 -13
- alita_sdk/runtime/utils/streamlit.py +33 -30
- alita_sdk/runtime/utils/utils.py +5 -0
- alita_sdk/tools/__init__.py +4 -0
- alita_sdk/tools/ado/repos/repos_wrapper.py +20 -13
- alita_sdk/tools/aws/__init__.py +7 -0
- alita_sdk/tools/aws/delta_lake/__init__.py +136 -0
- alita_sdk/tools/aws/delta_lake/api_wrapper.py +220 -0
- alita_sdk/tools/aws/delta_lake/schemas.py +20 -0
- alita_sdk/tools/aws/delta_lake/tool.py +35 -0
- 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 +55 -5
- 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/google/__init__.py +7 -0
- alita_sdk/tools/google/bigquery/__init__.py +154 -0
- alita_sdk/tools/google/bigquery/api_wrapper.py +502 -0
- alita_sdk/tools/google/bigquery/schemas.py +102 -0
- alita_sdk/tools/google/bigquery/tool.py +34 -0
- alita_sdk/tools/llm/llm_utils.py +0 -6
- alita_sdk/tools/openapi/__init__.py +14 -3
- alita_sdk/tools/sharepoint/__init__.py +2 -1
- alita_sdk/tools/sharepoint/api_wrapper.py +71 -7
- alita_sdk/tools/testrail/__init__.py +9 -1
- alita_sdk/tools/testrail/api_wrapper.py +154 -5
- alita_sdk/tools/utils/content_parser.py +77 -13
- alita_sdk/tools/zephyr_scale/api_wrapper.py +271 -22
- {alita_sdk-0.3.204.dist-info → alita_sdk-0.3.206.dist-info}/METADATA +3 -1
- {alita_sdk-0.3.204.dist-info → alita_sdk-0.3.206.dist-info}/RECORD +39 -30
- alita_sdk/runtime/llms/alita.py +0 -259
- {alita_sdk-0.3.204.dist-info → alita_sdk-0.3.206.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.204.dist-info → alita_sdk-0.3.206.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.204.dist-info → alita_sdk-0.3.206.dist-info}/top_level.txt +0 -0
@@ -17,6 +17,21 @@ if TYPE_CHECKING:
|
|
17
17
|
pass
|
18
18
|
|
19
19
|
|
20
|
+
def normalize_response(response) -> Dict[str, Any]:
|
21
|
+
"""
|
22
|
+
Normalize API response to dictionary format.
|
23
|
+
Handles different response types from Bitbucket APIs.
|
24
|
+
"""
|
25
|
+
if isinstance(response, dict):
|
26
|
+
return response
|
27
|
+
if hasattr(response, 'to_dict'):
|
28
|
+
return response.to_dict()
|
29
|
+
if hasattr(response, '__dict__'):
|
30
|
+
return {k: v for k, v in response.__dict__.items()
|
31
|
+
if isinstance(v, (str, int, float, bool, list, dict, type(None)))}
|
32
|
+
return {"raw_response": str(response)}
|
33
|
+
|
34
|
+
|
20
35
|
class BitbucketApiAbstract(ABC):
|
21
36
|
|
22
37
|
@abstractmethod
|
@@ -48,11 +63,11 @@ class BitbucketApiAbstract(ABC):
|
|
48
63
|
pass
|
49
64
|
|
50
65
|
@abstractmethod
|
51
|
-
def get_pull_request(self, pr_id: str) -> Any:
|
66
|
+
def get_pull_request(self, pr_id: str) -> Dict[str, Any]:
|
52
67
|
pass
|
53
68
|
|
54
69
|
@abstractmethod
|
55
|
-
def get_pull_requests_changes(self, pr_id: str) -> Any:
|
70
|
+
def get_pull_requests_changes(self, pr_id: str) -> Dict[str, Any]:
|
56
71
|
pass
|
57
72
|
|
58
73
|
@abstractmethod
|
@@ -95,7 +110,7 @@ class BitbucketServerApi(BitbucketApiAbstract):
|
|
95
110
|
|
96
111
|
def get_files_list(self, file_path: str, branch: str) -> list:
|
97
112
|
files = self.api_client.get_file_list(project_key=self.project, repository_slug=self.repository, query=branch,
|
98
|
-
|
113
|
+
sub_folder=file_path)
|
99
114
|
files_list = []
|
100
115
|
for file in files:
|
101
116
|
files_list.append(file['path'])
|
@@ -112,7 +127,7 @@ class BitbucketServerApi(BitbucketApiAbstract):
|
|
112
127
|
)
|
113
128
|
|
114
129
|
def update_file(self, file_path: str, update_query: str, branch: str) -> str:
|
115
|
-
file_content = self.get_file(file_path
|
130
|
+
file_content = self.get_file(file_path=file_path, branch=branch)
|
116
131
|
updated_file_content = file_content
|
117
132
|
for old, new in extract_old_new_pairs(update_query):
|
118
133
|
if not old.strip():
|
@@ -126,8 +141,8 @@ class BitbucketServerApi(BitbucketApiAbstract):
|
|
126
141
|
"the current file contents."
|
127
142
|
)
|
128
143
|
|
129
|
-
|
130
|
-
|
144
|
+
source_commit_generator = self.api_client.get_commits(project_key=self.project, repository_slug=self.repository,
|
145
|
+
hash_newest=branch, limit=1)
|
131
146
|
source_commit = next(source_commit_generator)
|
132
147
|
return self.api_client.update_file(
|
133
148
|
project_key=self.project,
|
@@ -138,7 +153,7 @@ class BitbucketServerApi(BitbucketApiAbstract):
|
|
138
153
|
filename=file_path,
|
139
154
|
source_commit_id=source_commit['id']
|
140
155
|
)
|
141
|
-
|
156
|
+
|
142
157
|
def get_pull_request_commits(self, pr_id: str) -> List[Dict[str, Any]]:
|
143
158
|
"""
|
144
159
|
Get commits from a pull request
|
@@ -147,27 +162,32 @@ class BitbucketServerApi(BitbucketApiAbstract):
|
|
147
162
|
Returns:
|
148
163
|
List[Dict[str, Any]]: List of commits in the pull request
|
149
164
|
"""
|
150
|
-
return self.api_client.get_pull_requests_commits(project_key=self.project, repository_slug=self.repository,
|
151
|
-
|
165
|
+
return self.api_client.get_pull_requests_commits(project_key=self.project, repository_slug=self.repository,
|
166
|
+
pull_request_id=pr_id)
|
167
|
+
|
152
168
|
def get_pull_request(self, pr_id):
|
153
169
|
""" Get details of a pull request
|
154
170
|
Parameters:
|
155
171
|
pr_id(str): the pull request ID
|
156
172
|
Returns:
|
157
|
-
Any: Details of the pull request
|
173
|
+
Dict[str, Any]: Details of the pull request
|
158
174
|
"""
|
159
|
-
|
160
|
-
|
161
|
-
|
175
|
+
response = self.api_client.get_pull_request(project_key=self.project, repository_slug=self.repository,
|
176
|
+
pull_request_id=pr_id)
|
177
|
+
return normalize_response(response)
|
178
|
+
|
179
|
+
def get_pull_requests_changes(self, pr_id: str) -> Dict[str, Any]:
|
162
180
|
"""
|
163
181
|
Get changes of a pull request
|
164
182
|
Parameters:
|
165
183
|
pr_id(str): the pull request ID
|
166
184
|
Returns:
|
167
|
-
Any: Changes of the pull request
|
185
|
+
Dict[str, Any]: Changes of the pull request
|
168
186
|
"""
|
169
|
-
|
170
|
-
|
187
|
+
response = self.api_client.get_pull_requests_changes(project_key=self.project, repository_slug=self.repository,
|
188
|
+
pull_request_id=pr_id)
|
189
|
+
return normalize_response(response)
|
190
|
+
|
171
191
|
def add_pull_request_comment(self, pr_id, content, inline=None):
|
172
192
|
"""
|
173
193
|
Add a comment to a pull request. Supports multiple content types and inline comments.
|
@@ -204,6 +224,7 @@ class BitbucketServerApi(BitbucketApiAbstract):
|
|
204
224
|
**comment_data
|
205
225
|
)
|
206
226
|
|
227
|
+
|
207
228
|
class BitbucketCloudApi(BitbucketApiAbstract):
|
208
229
|
api_client: Cloud
|
209
230
|
|
@@ -249,8 +270,9 @@ class BitbucketCloudApi(BitbucketApiAbstract):
|
|
249
270
|
index = 0
|
250
271
|
# TODO: add pagination
|
251
272
|
for item in \
|
252
|
-
|
253
|
-
|
273
|
+
self.repository.get(
|
274
|
+
path=f'src/{branch}/{file_path}?max_depth=100&pagelen=100&fields=values.path&q=type="commit_file"')[
|
275
|
+
'values']:
|
254
276
|
files_list.append(item['path'])
|
255
277
|
return files_list
|
256
278
|
|
@@ -259,7 +281,8 @@ class BitbucketCloudApi(BitbucketApiAbstract):
|
|
259
281
|
'branch': f'{branch}',
|
260
282
|
f'{file_path}': f'{file_contents}',
|
261
283
|
}
|
262
|
-
return self.repository.post(path='src', data=form_data, files={},
|
284
|
+
return self.repository.post(path='src', data=form_data, files={},
|
285
|
+
headers={'Content-Type': 'application/x-www-form-urlencoded'})
|
263
286
|
|
264
287
|
def update_file(self, file_path: str, update_query: str, branch: str) -> ToolException | str:
|
265
288
|
|
@@ -277,7 +300,7 @@ class BitbucketCloudApi(BitbucketApiAbstract):
|
|
277
300
|
"the current file contents."
|
278
301
|
)
|
279
302
|
return self.create_file(file_path, updated_file_content, branch)
|
280
|
-
|
303
|
+
|
281
304
|
def get_pull_request_commits(self, pr_id: str) -> List[Dict[str, Any]]:
|
282
305
|
"""
|
283
306
|
Get commits from a pull request
|
@@ -287,26 +310,28 @@ class BitbucketCloudApi(BitbucketApiAbstract):
|
|
287
310
|
List[Dict[str, Any]]: List of commits in the pull request
|
288
311
|
"""
|
289
312
|
return self.repository.pullrequests.get(pr_id).get('commits', {}).get('values', [])
|
290
|
-
|
291
|
-
def get_pull_request(self, pr_id: str) -> Any:
|
313
|
+
|
314
|
+
def get_pull_request(self, pr_id: str) -> Dict[str, Any]:
|
292
315
|
""" Get details of a pull request
|
293
316
|
Parameters:
|
294
317
|
pr_id(str): the pull request ID
|
295
318
|
Returns:
|
296
|
-
Any: Details of the pull request
|
319
|
+
Dict[str, Any]: Details of the pull request
|
297
320
|
"""
|
298
|
-
|
299
|
-
|
300
|
-
|
321
|
+
response = self.repository.pullrequests.get(pr_id)
|
322
|
+
return normalize_response(response)
|
323
|
+
|
324
|
+
def get_pull_requests_changes(self, pr_id: str) -> Dict[str, Any]:
|
301
325
|
"""
|
302
326
|
Get changes of a pull request
|
303
327
|
Parameters:
|
304
328
|
pr_id(str): the pull request ID
|
305
329
|
Returns:
|
306
|
-
Any: Changes of the pull request
|
330
|
+
Dict[str, Any]: Changes of the pull request
|
307
331
|
"""
|
308
|
-
|
309
|
-
|
332
|
+
response = self.repository.pullrequests.get(pr_id).get('diff', {})
|
333
|
+
return normalize_response(response)
|
334
|
+
|
310
335
|
def add_pull_request_comment(self, pr_id: str, content, inline=None) -> str:
|
311
336
|
"""
|
312
337
|
Add a comment to a pull request. Supports multiple content types and inline comments.
|
alita_sdk/tools/elitea_base.py
CHANGED
@@ -2,7 +2,9 @@ import ast
|
|
2
2
|
import fnmatch
|
3
3
|
import logging
|
4
4
|
import traceback
|
5
|
-
from typing import Any, Optional, List, Dict
|
5
|
+
from typing import Any, Optional, List, Dict, Generator
|
6
|
+
|
7
|
+
from langchain_core.documents import Document
|
6
8
|
from langchain_core.tools import ToolException
|
7
9
|
from pydantic import BaseModel, create_model, Field
|
8
10
|
from .utils import TOOLKIT_SPLITTER
|
@@ -186,7 +188,46 @@ class BaseToolApiWrapper(BaseModel):
|
|
186
188
|
|
187
189
|
class BaseVectorStoreToolApiWrapper(BaseToolApiWrapper):
|
188
190
|
"""Base class for tool API wrappers that support vector store functionality."""
|
189
|
-
|
191
|
+
|
192
|
+
doctype: str = "document"
|
193
|
+
|
194
|
+
def _base_loader(self, **kwargs) -> List[Document]:
|
195
|
+
""" Loads documents from a source, processes them,
|
196
|
+
and returns a list of Document objects with base metadata: id and created_on."""
|
197
|
+
pass
|
198
|
+
|
199
|
+
def _process_document(self, base_document: Document) -> Document:
|
200
|
+
""" Process an existing base document to extract relevant metadata for full document preparation.
|
201
|
+
Used for late processing of documents after we ensure that the document has to be indexed to avoid
|
202
|
+
time-consuming operations for documents which might be useless.
|
203
|
+
|
204
|
+
Args:
|
205
|
+
document (Document): The base document to process.
|
206
|
+
|
207
|
+
Returns:
|
208
|
+
Document: The processed document with metadata."""
|
209
|
+
pass
|
210
|
+
|
211
|
+
def _process_documents(self, documents: List[Document]) -> Generator[Document, None, None]:
|
212
|
+
"""
|
213
|
+
Process a list of base documents to extract relevant metadata for full document preparation.
|
214
|
+
Used for late processing of documents after we ensure that the documents have to be indexed to avoid
|
215
|
+
time-consuming operations for documents which might be useless.
|
216
|
+
This function passed to index_documents method of vector store and called after _reduce_duplicates method.
|
217
|
+
|
218
|
+
Args:
|
219
|
+
documents (List[Document]): The base documents to process.
|
220
|
+
|
221
|
+
Returns:
|
222
|
+
Generator[Document, None, None]: A generator yielding processed documents with metadata.
|
223
|
+
"""
|
224
|
+
for doc in documents:
|
225
|
+
processed_docs = self._process_document(doc)
|
226
|
+
if processed_docs: # Only proceed if the list is not empty
|
227
|
+
for processed_doc in processed_docs:
|
228
|
+
yield processed_doc
|
229
|
+
|
230
|
+
|
190
231
|
def _init_vector_store(self, collection_suffix: str = "", embeddings: Optional[Any] = None):
|
191
232
|
""" Initializes the vector store wrapper with the provided parameters."""
|
192
233
|
try:
|
@@ -225,7 +266,8 @@ class BaseVectorStoreToolApiWrapper(BaseToolApiWrapper):
|
|
225
266
|
embedding_model=self.embedding_model,
|
226
267
|
embedding_model_params=self.embedding_model_params,
|
227
268
|
vectorstore_params=vectorstore_params,
|
228
|
-
embeddings=embeddings
|
269
|
+
embeddings=embeddings,
|
270
|
+
process_document_func=self._process_documents,
|
229
271
|
)
|
230
272
|
|
231
273
|
def search_index(self,
|
@@ -345,7 +387,7 @@ class BaseCodeToolApiWrapper(BaseVectorStoreToolApiWrapper):
|
|
345
387
|
Handles the retrieval of files from a specific path and branch.
|
346
388
|
This method should be implemented in subclasses to provide the actual file retrieval logic.
|
347
389
|
"""
|
348
|
-
_files = self._get_files(path, branch)
|
390
|
+
_files = self._get_files(path=path, branch=branch)
|
349
391
|
if isinstance(_files, str):
|
350
392
|
try:
|
351
393
|
# Attempt to convert the string to a list using ast.literal_eval
|
@@ -447,4 +489,12 @@ class BaseCodeToolApiWrapper(BaseVectorStoreToolApiWrapper):
|
|
447
489
|
}
|
448
490
|
|
449
491
|
# Return index_data tool first, then the search tools
|
450
|
-
return [index_tool] + base_tools
|
492
|
+
return [index_tool] + base_tools
|
493
|
+
|
494
|
+
def extend_with_vector_tools(method):
|
495
|
+
def wrapper(self, *args, **kwargs):
|
496
|
+
tools = method(self, *args, **kwargs)
|
497
|
+
tools.extend(self._get_vector_search_tools())
|
498
|
+
return tools
|
499
|
+
|
500
|
+
return wrapper
|
@@ -1,16 +1,18 @@
|
|
1
1
|
from typing import Dict, List, Literal, Optional
|
2
2
|
|
3
|
+
from alita_sdk.tools.base.tool import BaseAction
|
3
4
|
from langchain_core.tools import BaseTool
|
4
5
|
from langchain_core.tools import BaseToolkit
|
5
6
|
from pydantic import create_model, BaseModel, ConfigDict, SecretStr
|
6
7
|
from pydantic.fields import Field
|
7
8
|
|
8
9
|
from .api_wrapper import GitLabAPIWrapper
|
9
|
-
from .tools import __all__
|
10
|
+
# from .tools import __all__
|
10
11
|
from ..utils import clean_string, TOOLKIT_SPLITTER, get_max_toolkit_length
|
11
12
|
|
12
13
|
name = "gitlab"
|
13
14
|
|
15
|
+
|
14
16
|
def get_tools(tool):
|
15
17
|
return AlitaGitlabToolkit().get_toolkit(
|
16
18
|
selected_tools=tool['settings'].get('selected_tools', []),
|
@@ -18,6 +20,15 @@ def get_tools(tool):
|
|
18
20
|
repository=tool['settings']['repository'],
|
19
21
|
branch=tool['settings']['branch'],
|
20
22
|
private_token=tool['settings']['private_token'],
|
23
|
+
|
24
|
+
llm=tool['settings'].get('llm', None),
|
25
|
+
alita=tool['settings'].get('alita', None),
|
26
|
+
connection_string=tool['settings'].get('connection_string', None),
|
27
|
+
collection_name=f"{tool.get('toolkit_name')}_{str(tool['id'])}",
|
28
|
+
doctype='code',
|
29
|
+
embedding_model="HuggingFaceEmbeddings",
|
30
|
+
embedding_model_params={"model_name": "sentence-transformers/all-MiniLM-L6-v2"},
|
31
|
+
vectorstore_type="PGVector",
|
21
32
|
toolkit_name=tool.get('toolkit_name')
|
22
33
|
).get_tools()
|
23
34
|
|
@@ -27,10 +38,8 @@ class AlitaGitlabToolkit(BaseToolkit):
|
|
27
38
|
|
28
39
|
@staticmethod
|
29
40
|
def toolkit_config_schema() -> BaseModel:
|
30
|
-
selected_tools = {
|
31
|
-
|
32
|
-
default = t['tool'].__pydantic_fields__['args_schema'].default
|
33
|
-
selected_tools[t['name']] = default.schema() if default else default
|
41
|
+
selected_tools = {x['name']: x['args_schema'].schema() for x in
|
42
|
+
GitLabAPIWrapper.model_construct().get_available_tools()}
|
34
43
|
AlitaGitlabToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
|
35
44
|
return create_model(
|
36
45
|
name,
|
@@ -66,15 +75,18 @@ class AlitaGitlabToolkit(BaseToolkit):
|
|
66
75
|
selected_tools = []
|
67
76
|
gitlab_api_wrapper = GitLabAPIWrapper(**kwargs)
|
68
77
|
prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
|
69
|
-
available_tools: List[Dict] =
|
78
|
+
available_tools: List[Dict] = gitlab_api_wrapper.get_available_tools()
|
70
79
|
tools = []
|
71
80
|
for tool in available_tools:
|
72
81
|
if selected_tools:
|
73
|
-
if tool[
|
82
|
+
if tool["name"] not in selected_tools:
|
74
83
|
continue
|
75
|
-
|
76
|
-
|
77
|
-
|
84
|
+
tools.append(BaseAction(
|
85
|
+
api_wrapper=gitlab_api_wrapper,
|
86
|
+
name=prefix + tool["name"],
|
87
|
+
description=tool["description"] + "\nrepo: " + gitlab_api_wrapper.repository,
|
88
|
+
args_schema=tool["args_schema"]
|
89
|
+
))
|
78
90
|
return cls(tools=tools)
|
79
91
|
|
80
92
|
def get_tools(self):
|