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
@@ -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
- sub_folder=file_path)
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 = file_path, branch=branch)
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
- source_commit_generator = self.api_client.get_commits(project_key=self.project, repository_slug=self.repository, hash_newest=branch, limit=1)
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, pull_request_id=pr_id)
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
- return self.api_client.get_pull_request(project_key=self.project, repository_slug=self.repository, pull_request_id=pr_id)
160
-
161
- def get_pull_requests_changes(self, pr_id: str) -> Any:
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
- return self.api_client.get_pull_requests_changes(project_key=self.project, repository_slug=self.repository, pull_request_id=pr_id)
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
- self.repository.get(path=f'src/{branch}/{file_path}?max_depth=100&pagelen=100&fields=values.path&q=type="commit_file"')[
253
- 'values']:
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={}, headers={'Content-Type': 'application/x-www-form-urlencoded'})
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
- return self.repository.pullrequests.get(pr_id)
299
-
300
- def get_pull_requests_changes(self, pr_id: str) -> Any:
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
- return self.repository.pullrequests.get(pr_id).get('diff', {})
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.
@@ -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
- for t in __all__:
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] = __all__
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['name'] not in selected_tools:
82
+ if tool["name"] not in selected_tools:
74
83
  continue
75
- initiated_tool = tool['tool'](api_wrapper=gitlab_api_wrapper)
76
- initiated_tool.name = prefix + tool['name']
77
- tools.append(initiated_tool)
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):