alita-sdk 0.3.263__py3-none-any.whl → 0.3.499__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 (248) hide show
  1. alita_sdk/cli/__init__.py +10 -0
  2. alita_sdk/cli/__main__.py +17 -0
  3. alita_sdk/cli/agent/__init__.py +5 -0
  4. alita_sdk/cli/agent/default.py +258 -0
  5. alita_sdk/cli/agent_executor.py +155 -0
  6. alita_sdk/cli/agent_loader.py +215 -0
  7. alita_sdk/cli/agent_ui.py +228 -0
  8. alita_sdk/cli/agents.py +3601 -0
  9. alita_sdk/cli/callbacks.py +647 -0
  10. alita_sdk/cli/cli.py +168 -0
  11. alita_sdk/cli/config.py +306 -0
  12. alita_sdk/cli/context/__init__.py +30 -0
  13. alita_sdk/cli/context/cleanup.py +198 -0
  14. alita_sdk/cli/context/manager.py +731 -0
  15. alita_sdk/cli/context/message.py +285 -0
  16. alita_sdk/cli/context/strategies.py +289 -0
  17. alita_sdk/cli/context/token_estimation.py +127 -0
  18. alita_sdk/cli/formatting.py +182 -0
  19. alita_sdk/cli/input_handler.py +419 -0
  20. alita_sdk/cli/inventory.py +1256 -0
  21. alita_sdk/cli/mcp_loader.py +315 -0
  22. alita_sdk/cli/toolkit.py +327 -0
  23. alita_sdk/cli/toolkit_loader.py +85 -0
  24. alita_sdk/cli/tools/__init__.py +43 -0
  25. alita_sdk/cli/tools/approval.py +224 -0
  26. alita_sdk/cli/tools/filesystem.py +1751 -0
  27. alita_sdk/cli/tools/planning.py +389 -0
  28. alita_sdk/cli/tools/terminal.py +414 -0
  29. alita_sdk/community/__init__.py +64 -8
  30. alita_sdk/community/inventory/__init__.py +224 -0
  31. alita_sdk/community/inventory/config.py +257 -0
  32. alita_sdk/community/inventory/enrichment.py +2137 -0
  33. alita_sdk/community/inventory/extractors.py +1469 -0
  34. alita_sdk/community/inventory/ingestion.py +3172 -0
  35. alita_sdk/community/inventory/knowledge_graph.py +1457 -0
  36. alita_sdk/community/inventory/parsers/__init__.py +218 -0
  37. alita_sdk/community/inventory/parsers/base.py +295 -0
  38. alita_sdk/community/inventory/parsers/csharp_parser.py +907 -0
  39. alita_sdk/community/inventory/parsers/go_parser.py +851 -0
  40. alita_sdk/community/inventory/parsers/html_parser.py +389 -0
  41. alita_sdk/community/inventory/parsers/java_parser.py +593 -0
  42. alita_sdk/community/inventory/parsers/javascript_parser.py +629 -0
  43. alita_sdk/community/inventory/parsers/kotlin_parser.py +768 -0
  44. alita_sdk/community/inventory/parsers/markdown_parser.py +362 -0
  45. alita_sdk/community/inventory/parsers/python_parser.py +604 -0
  46. alita_sdk/community/inventory/parsers/rust_parser.py +858 -0
  47. alita_sdk/community/inventory/parsers/swift_parser.py +832 -0
  48. alita_sdk/community/inventory/parsers/text_parser.py +322 -0
  49. alita_sdk/community/inventory/parsers/yaml_parser.py +370 -0
  50. alita_sdk/community/inventory/patterns/__init__.py +61 -0
  51. alita_sdk/community/inventory/patterns/ast_adapter.py +380 -0
  52. alita_sdk/community/inventory/patterns/loader.py +348 -0
  53. alita_sdk/community/inventory/patterns/registry.py +198 -0
  54. alita_sdk/community/inventory/presets.py +535 -0
  55. alita_sdk/community/inventory/retrieval.py +1403 -0
  56. alita_sdk/community/inventory/toolkit.py +173 -0
  57. alita_sdk/community/inventory/visualize.py +1370 -0
  58. alita_sdk/configurations/__init__.py +10 -0
  59. alita_sdk/configurations/ado.py +4 -2
  60. alita_sdk/configurations/azure_search.py +1 -1
  61. alita_sdk/configurations/bigquery.py +1 -1
  62. alita_sdk/configurations/bitbucket.py +94 -2
  63. alita_sdk/configurations/browser.py +18 -0
  64. alita_sdk/configurations/carrier.py +19 -0
  65. alita_sdk/configurations/confluence.py +96 -1
  66. alita_sdk/configurations/delta_lake.py +1 -1
  67. alita_sdk/configurations/figma.py +0 -5
  68. alita_sdk/configurations/github.py +65 -1
  69. alita_sdk/configurations/gitlab.py +79 -0
  70. alita_sdk/configurations/google_places.py +17 -0
  71. alita_sdk/configurations/jira.py +103 -0
  72. alita_sdk/configurations/postman.py +1 -1
  73. alita_sdk/configurations/qtest.py +1 -3
  74. alita_sdk/configurations/report_portal.py +19 -0
  75. alita_sdk/configurations/salesforce.py +19 -0
  76. alita_sdk/configurations/service_now.py +1 -12
  77. alita_sdk/configurations/sharepoint.py +19 -0
  78. alita_sdk/configurations/sonar.py +18 -0
  79. alita_sdk/configurations/sql.py +20 -0
  80. alita_sdk/configurations/testio.py +18 -0
  81. alita_sdk/configurations/testrail.py +88 -0
  82. alita_sdk/configurations/xray.py +94 -1
  83. alita_sdk/configurations/zephyr_enterprise.py +94 -1
  84. alita_sdk/configurations/zephyr_essential.py +95 -0
  85. alita_sdk/runtime/clients/artifact.py +12 -2
  86. alita_sdk/runtime/clients/client.py +235 -66
  87. alita_sdk/runtime/clients/mcp_discovery.py +342 -0
  88. alita_sdk/runtime/clients/mcp_manager.py +262 -0
  89. alita_sdk/runtime/clients/sandbox_client.py +373 -0
  90. alita_sdk/runtime/langchain/assistant.py +123 -17
  91. alita_sdk/runtime/langchain/constants.py +8 -1
  92. alita_sdk/runtime/langchain/document_loaders/AlitaDocxMammothLoader.py +315 -3
  93. alita_sdk/runtime/langchain/document_loaders/AlitaExcelLoader.py +209 -31
  94. alita_sdk/runtime/langchain/document_loaders/AlitaImageLoader.py +1 -1
  95. alita_sdk/runtime/langchain/document_loaders/AlitaJSONLoader.py +8 -2
  96. alita_sdk/runtime/langchain/document_loaders/AlitaMarkdownLoader.py +66 -0
  97. alita_sdk/runtime/langchain/document_loaders/AlitaPDFLoader.py +79 -10
  98. alita_sdk/runtime/langchain/document_loaders/AlitaPowerPointLoader.py +52 -15
  99. alita_sdk/runtime/langchain/document_loaders/AlitaPythonLoader.py +9 -0
  100. alita_sdk/runtime/langchain/document_loaders/AlitaTableLoader.py +1 -4
  101. alita_sdk/runtime/langchain/document_loaders/AlitaTextLoader.py +15 -2
  102. alita_sdk/runtime/langchain/document_loaders/ImageParser.py +30 -0
  103. alita_sdk/runtime/langchain/document_loaders/constants.py +187 -40
  104. alita_sdk/runtime/langchain/interfaces/llm_processor.py +4 -2
  105. alita_sdk/runtime/langchain/langraph_agent.py +406 -91
  106. alita_sdk/runtime/langchain/utils.py +51 -8
  107. alita_sdk/runtime/llms/preloaded.py +2 -6
  108. alita_sdk/runtime/models/mcp_models.py +61 -0
  109. alita_sdk/runtime/toolkits/__init__.py +26 -0
  110. alita_sdk/runtime/toolkits/application.py +9 -2
  111. alita_sdk/runtime/toolkits/artifact.py +19 -7
  112. alita_sdk/runtime/toolkits/datasource.py +13 -6
  113. alita_sdk/runtime/toolkits/mcp.py +780 -0
  114. alita_sdk/runtime/toolkits/planning.py +178 -0
  115. alita_sdk/runtime/toolkits/subgraph.py +11 -6
  116. alita_sdk/runtime/toolkits/tools.py +214 -60
  117. alita_sdk/runtime/toolkits/vectorstore.py +9 -4
  118. alita_sdk/runtime/tools/__init__.py +22 -0
  119. alita_sdk/runtime/tools/application.py +16 -4
  120. alita_sdk/runtime/tools/artifact.py +312 -19
  121. alita_sdk/runtime/tools/function.py +100 -4
  122. alita_sdk/runtime/tools/graph.py +81 -0
  123. alita_sdk/runtime/tools/image_generation.py +212 -0
  124. alita_sdk/runtime/tools/llm.py +539 -180
  125. alita_sdk/runtime/tools/mcp_inspect_tool.py +284 -0
  126. alita_sdk/runtime/tools/mcp_remote_tool.py +181 -0
  127. alita_sdk/runtime/tools/mcp_server_tool.py +3 -1
  128. alita_sdk/runtime/tools/planning/__init__.py +36 -0
  129. alita_sdk/runtime/tools/planning/models.py +246 -0
  130. alita_sdk/runtime/tools/planning/wrapper.py +607 -0
  131. alita_sdk/runtime/tools/router.py +2 -1
  132. alita_sdk/runtime/tools/sandbox.py +375 -0
  133. alita_sdk/runtime/tools/vectorstore.py +62 -63
  134. alita_sdk/runtime/tools/vectorstore_base.py +156 -85
  135. alita_sdk/runtime/utils/AlitaCallback.py +106 -20
  136. alita_sdk/runtime/utils/mcp_client.py +465 -0
  137. alita_sdk/runtime/utils/mcp_oauth.py +244 -0
  138. alita_sdk/runtime/utils/mcp_sse_client.py +405 -0
  139. alita_sdk/runtime/utils/mcp_tools_discovery.py +124 -0
  140. alita_sdk/runtime/utils/streamlit.py +41 -14
  141. alita_sdk/runtime/utils/toolkit_utils.py +28 -9
  142. alita_sdk/runtime/utils/utils.py +14 -0
  143. alita_sdk/tools/__init__.py +78 -35
  144. alita_sdk/tools/ado/__init__.py +0 -1
  145. alita_sdk/tools/ado/repos/__init__.py +10 -6
  146. alita_sdk/tools/ado/repos/repos_wrapper.py +12 -11
  147. alita_sdk/tools/ado/test_plan/__init__.py +10 -7
  148. alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +56 -23
  149. alita_sdk/tools/ado/wiki/__init__.py +10 -11
  150. alita_sdk/tools/ado/wiki/ado_wrapper.py +114 -28
  151. alita_sdk/tools/ado/work_item/__init__.py +10 -11
  152. alita_sdk/tools/ado/work_item/ado_wrapper.py +63 -10
  153. alita_sdk/tools/advanced_jira_mining/__init__.py +10 -7
  154. alita_sdk/tools/aws/delta_lake/__init__.py +13 -11
  155. alita_sdk/tools/azure_ai/search/__init__.py +11 -7
  156. alita_sdk/tools/base_indexer_toolkit.py +392 -86
  157. alita_sdk/tools/bitbucket/__init__.py +18 -11
  158. alita_sdk/tools/bitbucket/api_wrapper.py +52 -9
  159. alita_sdk/tools/bitbucket/cloud_api_wrapper.py +5 -5
  160. alita_sdk/tools/browser/__init__.py +40 -16
  161. alita_sdk/tools/browser/crawler.py +3 -1
  162. alita_sdk/tools/browser/utils.py +15 -6
  163. alita_sdk/tools/carrier/__init__.py +17 -17
  164. alita_sdk/tools/carrier/backend_reports_tool.py +8 -4
  165. alita_sdk/tools/carrier/excel_reporter.py +8 -4
  166. alita_sdk/tools/chunkers/__init__.py +3 -1
  167. alita_sdk/tools/chunkers/code/codeparser.py +1 -1
  168. alita_sdk/tools/chunkers/sematic/json_chunker.py +1 -0
  169. alita_sdk/tools/chunkers/sematic/markdown_chunker.py +97 -6
  170. alita_sdk/tools/chunkers/sematic/proposal_chunker.py +1 -1
  171. alita_sdk/tools/chunkers/universal_chunker.py +270 -0
  172. alita_sdk/tools/cloud/aws/__init__.py +9 -6
  173. alita_sdk/tools/cloud/azure/__init__.py +9 -6
  174. alita_sdk/tools/cloud/gcp/__init__.py +9 -6
  175. alita_sdk/tools/cloud/k8s/__init__.py +9 -6
  176. alita_sdk/tools/code/linter/__init__.py +7 -7
  177. alita_sdk/tools/code/loaders/codesearcher.py +3 -2
  178. alita_sdk/tools/code/sonar/__init__.py +18 -12
  179. alita_sdk/tools/code_indexer_toolkit.py +199 -0
  180. alita_sdk/tools/confluence/__init__.py +14 -11
  181. alita_sdk/tools/confluence/api_wrapper.py +198 -58
  182. alita_sdk/tools/confluence/loader.py +10 -0
  183. alita_sdk/tools/custom_open_api/__init__.py +9 -4
  184. alita_sdk/tools/elastic/__init__.py +8 -7
  185. alita_sdk/tools/elitea_base.py +543 -64
  186. alita_sdk/tools/figma/__init__.py +10 -8
  187. alita_sdk/tools/figma/api_wrapper.py +352 -153
  188. alita_sdk/tools/github/__init__.py +13 -11
  189. alita_sdk/tools/github/api_wrapper.py +9 -26
  190. alita_sdk/tools/github/github_client.py +75 -12
  191. alita_sdk/tools/github/schemas.py +2 -1
  192. alita_sdk/tools/gitlab/__init__.py +11 -10
  193. alita_sdk/tools/gitlab/api_wrapper.py +135 -45
  194. alita_sdk/tools/gitlab_org/__init__.py +11 -9
  195. alita_sdk/tools/google/bigquery/__init__.py +12 -13
  196. alita_sdk/tools/google_places/__init__.py +18 -10
  197. alita_sdk/tools/jira/__init__.py +14 -8
  198. alita_sdk/tools/jira/api_wrapper.py +315 -168
  199. alita_sdk/tools/keycloak/__init__.py +8 -7
  200. alita_sdk/tools/localgit/local_git.py +56 -54
  201. alita_sdk/tools/memory/__init__.py +27 -11
  202. alita_sdk/tools/non_code_indexer_toolkit.py +7 -2
  203. alita_sdk/tools/ocr/__init__.py +8 -7
  204. alita_sdk/tools/openapi/__init__.py +10 -1
  205. alita_sdk/tools/pandas/__init__.py +8 -7
  206. alita_sdk/tools/pandas/api_wrapper.py +7 -25
  207. alita_sdk/tools/postman/__init__.py +8 -10
  208. alita_sdk/tools/postman/api_wrapper.py +19 -8
  209. alita_sdk/tools/postman/postman_analysis.py +8 -1
  210. alita_sdk/tools/pptx/__init__.py +8 -9
  211. alita_sdk/tools/qtest/__init__.py +19 -13
  212. alita_sdk/tools/qtest/api_wrapper.py +1784 -88
  213. alita_sdk/tools/rally/__init__.py +10 -9
  214. alita_sdk/tools/report_portal/__init__.py +20 -15
  215. alita_sdk/tools/salesforce/__init__.py +19 -15
  216. alita_sdk/tools/servicenow/__init__.py +14 -11
  217. alita_sdk/tools/sharepoint/__init__.py +14 -13
  218. alita_sdk/tools/sharepoint/api_wrapper.py +179 -39
  219. alita_sdk/tools/sharepoint/authorization_helper.py +191 -1
  220. alita_sdk/tools/sharepoint/utils.py +8 -2
  221. alita_sdk/tools/slack/__init__.py +10 -7
  222. alita_sdk/tools/sql/__init__.py +19 -18
  223. alita_sdk/tools/sql/api_wrapper.py +71 -23
  224. alita_sdk/tools/testio/__init__.py +18 -12
  225. alita_sdk/tools/testrail/__init__.py +10 -10
  226. alita_sdk/tools/testrail/api_wrapper.py +213 -45
  227. alita_sdk/tools/utils/__init__.py +28 -4
  228. alita_sdk/tools/utils/content_parser.py +181 -61
  229. alita_sdk/tools/utils/text_operations.py +254 -0
  230. alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +83 -27
  231. alita_sdk/tools/xray/__init__.py +12 -7
  232. alita_sdk/tools/xray/api_wrapper.py +58 -113
  233. alita_sdk/tools/zephyr/__init__.py +9 -6
  234. alita_sdk/tools/zephyr_enterprise/__init__.py +13 -8
  235. alita_sdk/tools/zephyr_enterprise/api_wrapper.py +17 -7
  236. alita_sdk/tools/zephyr_essential/__init__.py +13 -9
  237. alita_sdk/tools/zephyr_essential/api_wrapper.py +289 -47
  238. alita_sdk/tools/zephyr_essential/client.py +6 -4
  239. alita_sdk/tools/zephyr_scale/__init__.py +10 -7
  240. alita_sdk/tools/zephyr_scale/api_wrapper.py +6 -2
  241. alita_sdk/tools/zephyr_squad/__init__.py +9 -6
  242. {alita_sdk-0.3.263.dist-info → alita_sdk-0.3.499.dist-info}/METADATA +180 -33
  243. alita_sdk-0.3.499.dist-info/RECORD +433 -0
  244. alita_sdk-0.3.499.dist-info/entry_points.txt +2 -0
  245. alita_sdk-0.3.263.dist-info/RECORD +0 -342
  246. {alita_sdk-0.3.263.dist-info → alita_sdk-0.3.499.dist-info}/WHEEL +0 -0
  247. {alita_sdk-0.3.263.dist-info → alita_sdk-0.3.499.dist-info}/licenses/LICENSE +0 -0
  248. {alita_sdk-0.3.263.dist-info → alita_sdk-0.3.499.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,4 @@
1
+ import hashlib
1
2
  import json
2
3
  import logging
3
4
  from typing import Optional, Generator, Literal
@@ -9,6 +10,8 @@ from langchain_core.tools import ToolException
9
10
 
10
11
  from ..non_code_indexer_toolkit import NonCodeIndexerToolkit
11
12
  from ..utils.available_tools_decorator import extend_with_parent_available_tools
13
+ from ..utils.content_parser import file_extension_by_chunker
14
+ from ...runtime.utils.utils import IndexerKeywords
12
15
 
13
16
 
14
17
  class ZephyrEssentialApiWrapper(NonCodeIndexerToolkit):
@@ -179,12 +182,43 @@ class ZephyrEssentialApiWrapper(NonCodeIndexerToolkit):
179
182
  def create_folder(self, json: str):
180
183
  """Create a new folder."""
181
184
  folder_data = self._parse_json(json)
185
+ if 'parentId' not in folder_data:
186
+ if 'parentName' in folder_data:
187
+ parent_folder_name = folder_data['parentName']
188
+
189
+ parent_folder = self.find_folder_by_name(parent_folder_name)
190
+
191
+ if isinstance(parent_folder, ToolException):
192
+ return ToolException(f"Folder with name '{parent_folder_name}' not found.")
193
+ else:
194
+ folder_data['parentId'] = parent_folder['id']
195
+
182
196
  return self._client.create_folder(folder_data)
183
197
 
184
198
  def get_folder(self, folder_id: str):
185
199
  """Retrieve details of a specific folder."""
186
200
  return self._client.get_folder(folder_id)
187
201
 
202
+ def find_folder_by_name(self, name: str, project_key: Optional[str] = None, folder_type: Optional[str] = None):
203
+ """
204
+ Find a folder by its name, ignoring case.
205
+
206
+ :param name: The name of the folder to search for.
207
+ :param project_key: Optional filter by project key.
208
+ :param folder_type: Optional filter by folder type.
209
+ :return: The folder details if found, otherwise None.
210
+ """
211
+ # Fetch all folders with optional filters
212
+ folders = self.list_folders(project_key=project_key, folder_type=folder_type)
213
+
214
+ # Iterate through the folders and search for the matching name
215
+ for folder in folders['values']:
216
+ if folder.get('name', '').lower() == name.lower():
217
+ return folder
218
+
219
+ # Return None if no folder is found
220
+ return ToolException(f"Folder with name {name} was not found")
221
+
188
222
  def delete_link(self, link_id: str):
189
223
  """Delete a specific link."""
190
224
  return self._client.delete_link(link_id)
@@ -235,10 +269,11 @@ class ZephyrEssentialApiWrapper(NonCodeIndexerToolkit):
235
269
 
236
270
  def _index_tool_params(self):
237
271
  return {
238
- 'chunking_tool':(Literal['json'], Field(description="Name of chunking tool", default='json'))
272
+ 'chunking_tool':(Literal['json', ''], Field(description="Name of chunking tool", default='json'))
239
273
  }
240
274
 
241
275
  def _base_loader(self, **kwargs) -> Generator[Document, None, None]:
276
+ self._chunking_tool = kwargs.get('chunking_tool', None)
242
277
  try:
243
278
  test_cases = self.list_test_cases()
244
279
  except Exception as e:
@@ -250,21 +285,20 @@ class ZephyrEssentialApiWrapper(NonCodeIndexerToolkit):
250
285
  if isinstance(v, (str, int, float, bool, list, dict))
251
286
  }
252
287
  metadata['type'] = "TEST_CASE"
253
-
254
- yield Document(page_content="", metadata=metadata)
255
-
256
- def _extend_data(self, documents: Generator[Document, None, None]) -> Generator[Document, None, None]:
257
- for document in documents:
288
+ #
258
289
  try:
259
- if 'type' in document.metadata and document.metadata['type'] == "TEST_CASE":
260
- additional_content = self._process_test_case(document.metadata['key'])
261
- for steps_type, content in additional_content.items():
262
- if content:
263
- document.page_content = json.dumps(content)
264
- document.metadata["steps_type"] = steps_type
290
+ additional_content = self._process_test_case(metadata['key'])
291
+ for steps_type, content in additional_content.items():
292
+ if content:
293
+ page_content = json.dumps(content)
294
+ content_hash = hashlib.sha256(page_content.encode('utf-8')).hexdigest()
295
+ metadata[IndexerKeywords.UPDATED_ON.value] = content_hash
296
+ metadata[IndexerKeywords.CONTENT_IN_BYTES.value] = page_content.encode('utf-8')
297
+ metadata["steps_type"] = steps_type
265
298
  except Exception as e:
266
299
  logging.error(f"Failed to process document: {e}")
267
- yield document
300
+ #
301
+ yield Document(page_content="", metadata=metadata)
268
302
 
269
303
  def _process_test_case(self, key) -> dict:
270
304
  steps = self.get_test_case_test_steps(key)
@@ -482,6 +516,12 @@ class ZephyrEssentialApiWrapper(NonCodeIndexerToolkit):
482
516
  "args_schema": GetFolder,
483
517
  "ref": self.get_folder,
484
518
  },
519
+ {
520
+ "name": "find_folder_by_name",
521
+ "description": self.find_folder_by_name.__doc__,
522
+ "args_schema": FindFolderByName,
523
+ "ref": self.find_folder_by_name,
524
+ },
485
525
  {
486
526
  "name": "delete_link",
487
527
  "description": self.delete_link.__doc__,
@@ -577,8 +617,74 @@ UpdateTestCase = create_model(
577
617
  json=(str, Field(description=("""
578
618
  JSON body to update a test case. Example:
579
619
  {
580
- "name": "Updated Test Case Name",
581
- "description": "Updated Test Case Description"
620
+ "id": 1,
621
+ "key": "SA-T10",
622
+ "name": "Check axial pump",
623
+ "project": {
624
+ "id": 10005,
625
+ "self": "https://<api-base-url>/projects/10005"
626
+ },
627
+ "createdOn": "2018-05-15T13:15:13Z",
628
+ "objective": "To ensure the axial pump can be enabled",
629
+ "precondition": "Latest version of the axial pump available",
630
+ "estimatedTime": 138000,
631
+ "labels": [
632
+ "Regression",
633
+ "Performance",
634
+ "Automated"
635
+ ],
636
+ "component": {
637
+ "id": 10001,
638
+ "self": "https://<jira-instance>.atlassian.net/rest/api/2/component/10001"
639
+ },
640
+ "priority": {
641
+ "id": 10002,
642
+ "self": "https://<api-base-url>/priorities/10002"
643
+ },
644
+ "status": {
645
+ "id": 10000,
646
+ "self": "https://<api-base-url>/statuses/10000"
647
+ },
648
+ "folder": {
649
+ "id": 100006,
650
+ "self": "https://<api-base-url>/folders/10006"
651
+ },
652
+ "owner": {
653
+ "self": "https://<jira-instance>.atlassian.net/rest/api/2/user?accountId=5b10a2844c20165700ede21g",
654
+ "accountId": "5b10a2844c20165700ede21g"
655
+ },
656
+ "testScript": {
657
+ "self": "https://<api-base-url>/testCases/PROJ-T1/testscript"
658
+ },
659
+ "customFields": {
660
+ "Build Number": 20,
661
+ "Release Date": "2020-01-01",
662
+ "Pre-Condition(s)": "User should have logged in. <br> User should have navigated to the administration panel.",
663
+ "Implemented": false,
664
+ "Category": [
665
+ "Performance",
666
+ "Regression"
667
+ ],
668
+ "Tester": "fa2e582e-5e15-521e-92e3-47e6ca2e7256"
669
+ },
670
+ "links": {
671
+ "self": "string",
672
+ "issues": [
673
+ {
674
+ "self": "string",
675
+ "issueId": 10100,
676
+ "id": 1,
677
+ "target": "https://<jira-instance>.atlassian.net/rest/api/2/issue/10000",
678
+ "type": "COVERAGE"
679
+ }
680
+ ],
681
+ "webLinks": [
682
+ {
683
+ "self": "string",
684
+ "description": "A link to atlassian.com",
685
+ "url": "https://atlassian.com",
686
+ "id": 1,
687
+ "type": "COVERAGE"
582
688
  }
583
689
  """
584
690
  )))
@@ -595,9 +701,9 @@ CreateTestCaseIssueLink = create_model(
595
701
  json=(str, Field(description=("""
596
702
  JSON body to create an issue link. Example:
597
703
  {
598
- "issueKey": "ISSUE_KEY",
599
- "description": "Link Description"
704
+ "issueId": 10100
600
705
  }
706
+ where issueId - Jira issue id
601
707
  """
602
708
  )))
603
709
  )
@@ -639,8 +745,10 @@ CreateTestCaseTestScript = create_model(
639
745
  json=(str, Field(description=("""
640
746
  JSON body to create a test script. Example:
641
747
  {
642
- "script": "Test Script Content"
748
+ "type": "bdd",
749
+ "text": "Attempt to login to the application"
643
750
  }
751
+ Where type - Test script type. Allowed: plain, bdd
644
752
  """
645
753
  )))
646
754
  )
@@ -657,13 +765,43 @@ CreateTestCaseTestSteps = create_model(
657
765
  test_case_key=(str, Field(description="Key of the test case to create test steps for.")),
658
766
  json=(str, Field(description=("""
659
767
  JSON body to create test steps. Example:
660
- [
661
- {
662
- "step": "Step 1",
663
- "data": "Test Data",
664
- "result": "Expected Result"
665
- }
666
- ]
768
+ {
769
+ "mode": "APPEND",
770
+ "items": [
771
+ {
772
+ "inline": {
773
+ "description": "Attempt to login to the application",
774
+ "testData": "Username = SmartBear Password = weLoveAtlassian",
775
+ "expectedResult": "Login succeeds, web-app redirects to the dashboard view",
776
+ "customFields": {
777
+ "Build Number": 20,
778
+ "Release Date": "2020-01-01",
779
+ "Pre-Condition(s)": "User should have logged in. <br> User should have navigated to the administration panel.",
780
+ "Implemented": false,
781
+ "Category": [
782
+ "Performance",
783
+ "Regression"
784
+ ],
785
+ "Tester": "fa2e582e-5e15-521e-92e3-47e6ca2e7256"
786
+ }
787
+ },
788
+ "testCase": {
789
+ "self": "string",
790
+ "testCaseKey": "PROJ-T123",
791
+ "parameters": [
792
+ {
793
+ "name": "username",
794
+ "type": "DEFAULT_VALUE",
795
+ "value": "admin"
796
+ }
797
+ ]
798
+ }
799
+ }
800
+ ]
801
+ }
802
+ Where:
803
+ mode: str - required - Valid values: "APPEND", "OVERWRITE",
804
+ items - The list of test steps. Each step should be an object containing inline or testCase. They should only include one of these fields at a time.
667
805
  """
668
806
  )))
669
807
  )
@@ -701,9 +839,71 @@ UpdateTestCycle = create_model(
701
839
  json=(str, Field(description=("""
702
840
  JSON body to update a test cycle. Example:
703
841
  {
704
- "name": "Updated Test Cycle Name",
705
- "description": "Updated Test Cycle Description"
706
- }
842
+ "id": 1,
843
+ "key": "SA-R40",
844
+ "name": "Sprint 1 Regression Test Cycle",
845
+ "project": {
846
+ "id": 10005,
847
+ "self": "https://<api-base-url>/projects/10005"
848
+ },
849
+ "jiraProjectVersion": {
850
+ "id": 10000,
851
+ "self": "https://<jira-instance>.atlassian.net/rest/api/2/version/10000"
852
+ },
853
+ "status": {
854
+ "id": 10000,
855
+ "self": "https://<api-base-url>/statuses/10000"
856
+ },
857
+ "folder": {
858
+ "id": 100006,
859
+ "self": "https://<api-base-url>/folders/10006"
860
+ },
861
+ "description": "Regression test cycle 1 to ensure no breaking changes",
862
+ "plannedStartDate": "2018-05-19T13:15:13Z",
863
+ "plannedEndDate": "2018-05-20T13:15:13Z",
864
+ "owner": {
865
+ "self": "https://<jira-instance>.atlassian.net/rest/api/2/user?accountId=5b10a2844c20165700ede21g",
866
+ "accountId": "5b10a2844c20165700ede21g"
867
+ },
868
+ "customFields": {
869
+ "Build Number": 20,
870
+ "Release Date": "2020-01-01",
871
+ "Pre-Condition(s)": "User should have logged in. <br> User should have navigated to the administration panel.",
872
+ "Implemented": false,
873
+ "Category": [
874
+ "Performance",
875
+ "Regression"
876
+ ],
877
+ "Tester": "fa2e582e-5e15-521e-92e3-47e6ca2e7256"
878
+ },
879
+ "links": {
880
+ "self": "string",
881
+ "issues": [
882
+ {
883
+ "self": "string",
884
+ "issueId": 10100,
885
+ "id": 1,
886
+ "target": "https://<jira-instance>.atlassian.net/rest/api/2/issue/10000",
887
+ "type": "COVERAGE"
888
+ }
889
+ ],
890
+ "webLinks": [
891
+ {
892
+ "self": "string",
893
+ "description": "A link to atlassian.com",
894
+ "url": "https://atlassian.com",
895
+ "id": 1,
896
+ "type": "COVERAGE"
897
+ }
898
+ ],
899
+ "testPlans": [
900
+ {
901
+ "id": 1,
902
+ "self": "https://<api-base-url>/links/1",
903
+ "type": "RELATED",
904
+ "testPlanId": 2,
905
+ "target": "https://<jira-instance>.atlassian.net/rest/api/2/testplan/123"
906
+ }
707
907
  """
708
908
  )))
709
909
  )
@@ -719,9 +919,9 @@ CreateTestCycleIssueLink = create_model(
719
919
  json=(str, Field(description=("""
720
920
  JSON body to create an issue link. Example:
721
921
  {
722
- "issueKey": "ISSUE_KEY",
723
- "description": "Link Description"
922
+ "issueId": 10100
724
923
  }
924
+ where issueId - Jira issue id
725
925
  """
726
926
  )))
727
927
  )
@@ -753,10 +953,34 @@ CreateTestExecution = create_model(
753
953
  json=(str, Field(description=("""
754
954
  JSON body to create a test execution. Example:
755
955
  {
756
- "testCaseKey": "TEST_CASE_KEY",
757
- "testCycleKey": "TEST_CYCLE_KEY",
758
- "status": "PASS"
759
- }
956
+ "projectKey": "TIS",
957
+ "testCaseKey": "SA-T10",
958
+ "testCycleKey": "SA-R10",
959
+ "statusName": "In Progress",
960
+ "testScriptResults": [
961
+ {
962
+ "statusName": "In Progress",
963
+ "actualEndDate": "2018-05-20T13:15:13Z",
964
+ "actualResult": "User logged in successfully"
965
+ }
966
+ ],
967
+ "environmentName": "Chrome Latest Version",
968
+ "actualEndDate": "2018-05-20T13:15:13Z",
969
+ "executionTime": 120000,
970
+ "executedById": "5b10a2844c20165700ede21g",
971
+ "assignedToId": "5b10a2844c20165700ede21g",
972
+ "comment": "Test failed user could not login",
973
+ "customFields": {
974
+ "Build Number": 20,
975
+ "Release Date": "2020-01-01",
976
+ "Pre-Condition(s)": "User should have logged in. <br> User should have navigated to the administration panel.",
977
+ "Implemented": false,
978
+ "Category": [
979
+ "Performance",
980
+ "Regression"
981
+ ],
982
+ "Tester": "fa2e582e-5e15-521e-92e3-47e6ca2e7256"
983
+ }
760
984
  """
761
985
  )))
762
986
  )
@@ -772,8 +996,13 @@ UpdateTestExecution = create_model(
772
996
  json=(str, Field(description=("""
773
997
  JSON body to update a test execution. Example:
774
998
  {
775
- "status": "FAIL",
776
- "comment": "Updated comment"
999
+ "statusName": "In Progress",
1000
+ "environmentName": "Chrome Latest Version",
1001
+ "actualEndDate": "2018-05-20T13:15:13Z",
1002
+ "executionTime": 120000,
1003
+ "executedById": "5b10a2844c20165700ede21g",
1004
+ "assignedToId": "5b10a2844c20165700ede21g",
1005
+ "comment": "Test failed user could not login"
777
1006
  }
778
1007
  """
779
1008
  )))
@@ -791,12 +1020,14 @@ UpdateTestExecutionTestSteps = create_model(
791
1020
  test_execution_id_or_key=(str, Field(description="ID or key of the test execution to update test steps for.")),
792
1021
  json=(str, Field(description=("""
793
1022
  "JSON body to update test steps. Example:
794
- ["
795
- {"
796
- "step": "Step 1",
797
- "status": "PASS"
798
- }
799
- ]
1023
+ {
1024
+ "steps": [
1025
+ {
1026
+ "actualResult": "User logged in successfully",
1027
+ "statusName": "In Progress"
1028
+ }
1029
+ ]
1030
+ }
800
1031
  """
801
1032
  )))
802
1033
  )
@@ -817,9 +1048,9 @@ CreateTestExecutionIssueLink = create_model(
817
1048
  json=(str, Field(description=("""
818
1049
  JSON body to create an issue link. Example:
819
1050
  {
820
- "issueKey": "ISSUE_KEY",
821
- "description": "Link Description"
1051
+ "issueId": 10100
822
1052
  }
1053
+ where issueId - Jira issue id
823
1054
  """
824
1055
  )))
825
1056
  )
@@ -848,10 +1079,13 @@ CreateFolder = create_model(
848
1079
  json=(str, Field(description=("""
849
1080
  JSON body to create a folder. Example:
850
1081
  {
851
- "name": "Folder Name",
852
- "description": "Folder Description",
853
- "projectKey": "PROJECT_KEY"
1082
+ "parentId": 123456,
1083
+ "parentName": "parentFolder",
1084
+ "name": "ZephyrEssential_test",
1085
+ "projectKey": "PRJ",
1086
+ "folderType": "TEST_CASE"
854
1087
  }
1088
+ Possible folder types: "TEST_CASE", "TEST_PLAN", "TEST_CYCLE",
855
1089
  """
856
1090
  )))
857
1091
  )
@@ -861,6 +1095,14 @@ GetFolder = create_model(
861
1095
  folder_id=(str, Field(description="ID of the folder to retrieve."))
862
1096
  )
863
1097
 
1098
+ FindFolderByName = create_model(
1099
+ "GetFolder",
1100
+ name=(str, Field(description="Name of the folder to retrieve.")),
1101
+ project_key=(Optional[str], Field(description="Project key", default=None)),
1102
+ folder_type=(Optional[str], Field(description="""Folder type. Possible values: "TEST_CASE", "TEST_PLAN", "TEST_CYCLE" """,
1103
+ default=None)),
1104
+ )
1105
+
864
1106
  DeleteLink = create_model(
865
1107
  "DeleteLink",
866
1108
  link_id=(str, Field(description="ID of the link to delete."))
@@ -1,4 +1,5 @@
1
1
  import requests
2
+ from langchain_core.tools import ToolException
2
3
 
3
4
  class ZephyrEssentialAPI:
4
5
  def __init__(self, base_url: str, token: str):
@@ -14,10 +15,11 @@ class ZephyrEssentialAPI:
14
15
  })
15
16
  try:
16
17
  resp = requests.request(method=method, url=url, headers=headers, json=json, params=params, files=files)
17
- resp.raise_for_status()
18
- if resp.headers.get("Content-Type", "").startswith("application/json"):
19
- return resp.json()
20
- return resp.text
18
+ if resp.status_code < 300:
19
+ if resp.headers.get("Content-Type", "").startswith("application/json"):
20
+ return resp.json()
21
+ return resp.text
22
+ return ToolException(f"Error performing request {method} {api_path}: {resp.content}")
21
23
  except requests.RequestException as e:
22
24
  raise Exception(f"Error performing request {method} {api_path}: {str(e)}")
23
25
 
@@ -6,7 +6,8 @@ from pydantic import create_model, BaseModel, Field
6
6
 
7
7
  from .api_wrapper import ZephyrScaleApiWrapper
8
8
  from ..base.tool import BaseAction
9
- from ..utils import clean_string, get_max_toolkit_length, TOOLKIT_SPLITTER
9
+ from ..elitea_base import filter_missconfigured_index_tools
10
+ from ..utils import clean_string, get_max_toolkit_length
10
11
  from ...configurations.pgvector import PgVectorConfiguration
11
12
  from ...configurations.zephyr import ZephyrConfiguration
12
13
 
@@ -31,16 +32,14 @@ def get_tools(tool):
31
32
 
32
33
  class ZephyrScaleToolkit(BaseToolkit):
33
34
  tools: List[BaseTool] = []
34
- toolkit_max_length: int = 0
35
35
 
36
36
  @staticmethod
37
37
  def toolkit_config_schema() -> BaseModel:
38
38
  selected_tools = {x['name']: x['args_schema'].schema() for x in ZephyrScaleApiWrapper.model_construct().get_available_tools()}
39
- ZephyrScaleToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
40
39
  return create_model(
41
40
  name,
42
41
  max_results=(int, Field(default=100, description="Results count to show")),
43
- zephyr_configuration=(Optional[ZephyrConfiguration], Field(description="Zephyr Configuration",
42
+ zephyr_configuration=(ZephyrConfiguration, Field(description="Zephyr Configuration",
44
43
  json_schema_extra={'configuration_types': ['zephyr']})),
45
44
  pgvector_configuration=(Optional[PgVectorConfiguration], Field(default=None, description="PgVector Configuration",
46
45
  json_schema_extra={
@@ -63,6 +62,7 @@ class ZephyrScaleToolkit(BaseToolkit):
63
62
  )
64
63
 
65
64
  @classmethod
65
+ @filter_missconfigured_index_tools
66
66
  def get_toolkit(cls, selected_tools: list[str] | None = None, toolkit_name: Optional[str] = None, **kwargs):
67
67
  if selected_tools is None:
68
68
  selected_tools = []
@@ -73,17 +73,20 @@ class ZephyrScaleToolkit(BaseToolkit):
73
73
  **(kwargs.get('pgvector_configuration') or {}),
74
74
  }
75
75
  zephyr_wrapper = ZephyrScaleApiWrapper(**wrapper_payload)
76
- prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
77
76
  available_tools = zephyr_wrapper.get_available_tools()
78
77
  tools = []
79
78
  for tool in available_tools:
80
79
  if selected_tools:
81
80
  if tool["name"] not in selected_tools:
82
81
  continue
82
+ description = tool["description"]
83
+ if toolkit_name:
84
+ description = f"Toolkit: {toolkit_name}\n{description}"
85
+ description = description[:1000]
83
86
  tools.append(BaseAction(
84
87
  api_wrapper=zephyr_wrapper,
85
- name=prefix + tool["name"],
86
- description=tool["description"],
88
+ name=tool["name"],
89
+ description=description,
87
90
  args_schema=tool["args_schema"]
88
91
  ))
89
92
  return cls(tools=tools)
@@ -12,6 +12,8 @@ from langchain_core.documents import Document
12
12
 
13
13
  from ..non_code_indexer_toolkit import NonCodeIndexerToolkit
14
14
  from ..utils.available_tools_decorator import extend_with_parent_available_tools
15
+ from ..utils.content_parser import file_extension_by_chunker
16
+ from ...runtime.utils.utils import IndexerKeywords
15
17
 
16
18
  try:
17
19
  from alita_sdk.runtime.langchain.interfaces.llm_processor import get_embeddings
@@ -1196,6 +1198,7 @@ class ZephyrScaleApiWrapper(NonCodeIndexerToolkit):
1196
1198
  Returns a list of fields for index_data args schema.
1197
1199
  """
1198
1200
  return {
1201
+ "chunking_tool": (Literal['json', ''], Field(description="Name of chunking tool", default='json')),
1199
1202
  "project_key": (str, Field(description="Jira project key filter")),
1200
1203
  "jql":(str, Field(description="""JQL-like query for searching test cases.
1201
1204
  Supported fields:
@@ -1214,10 +1217,10 @@ class ZephyrScaleApiWrapper(NonCodeIndexerToolkit):
1214
1217
  Example:
1215
1218
  'folder = "Authentication" AND label in ("Smoke", "Critical") AND text ~ "login" AND orderBy = "name" AND orderDirection = "ASC"'
1216
1219
  """)),
1217
- 'chunking_tool': (Literal['json'], Field(description="Name of chunking tool", default='json'))
1218
1220
  }
1219
1221
 
1220
1222
  def _base_loader(self, project_key: str, jql: str, **kwargs) -> Generator[Document, None, None]:
1223
+ self._chunking_tool = kwargs.get('chunking_tool', None)
1221
1224
  for test_case_doc in self._get_test_cases_docs(project_key, jql):
1222
1225
  yield test_case_doc
1223
1226
  for folder_doc in self._get_folders_docs(project_key):
@@ -1284,7 +1287,8 @@ class ZephyrScaleApiWrapper(NonCodeIndexerToolkit):
1284
1287
  additional_content = self._process_test_case(document.metadata['key'])
1285
1288
  for steps_type, content in additional_content.items():
1286
1289
  if content:
1287
- document.page_content = json.dumps(content)
1290
+ page_content = json.dumps(content)
1291
+ document.metadata[IndexerKeywords.CONTENT_IN_BYTES.value] = page_content.encode('utf-8')
1288
1292
  document.metadata["steps_type"] = steps_type
1289
1293
  except Exception as e:
1290
1294
  logging.error(f"Failed to process document: {e}")
@@ -5,7 +5,8 @@ from pydantic import create_model, BaseModel, Field, SecretStr
5
5
 
6
6
  from .api_wrapper import ZephyrSquadApiWrapper
7
7
  from ..base.tool import BaseAction
8
- from ..utils import clean_string, TOOLKIT_SPLITTER, get_max_toolkit_length
8
+ from ..elitea_base import filter_missconfigured_index_tools
9
+ from ..utils import clean_string, get_max_toolkit_length
9
10
 
10
11
  name = "zephyr_squad"
11
12
 
@@ -20,12 +21,10 @@ def get_tools(tool):
20
21
 
21
22
  class ZephyrSquadToolkit(BaseToolkit):
22
23
  tools: List[BaseTool] = []
23
- toolkit_max_length: int = 0
24
24
 
25
25
  @staticmethod
26
26
  def toolkit_config_schema() -> BaseModel:
27
27
  selected_tools = {x['name']: x['args_schema'].schema() for x in ZephyrSquadApiWrapper.model_construct().get_available_tools()}
28
- ZephyrSquadToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
29
28
  return create_model(
30
29
  name,
31
30
  account_id=(str, Field(description="AccountID for the user that is going to be authenticating")),
@@ -39,19 +38,23 @@ class ZephyrSquadToolkit(BaseToolkit):
39
38
  )
40
39
 
41
40
  @classmethod
41
+ @filter_missconfigured_index_tools
42
42
  def get_toolkit(cls, selected_tools: list[str] | None = None, toolkit_name: Optional[str] = None, **kwargs):
43
43
  zephyr_api_wrapper = ZephyrSquadApiWrapper(**kwargs)
44
- prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
45
44
  available_tools = zephyr_api_wrapper.get_available_tools()
46
45
  tools = []
47
46
  for tool in available_tools:
48
47
  if selected_tools:
49
48
  if tool["name"] not in selected_tools:
50
49
  continue
50
+ description = tool["description"]
51
+ if toolkit_name:
52
+ description = f"Toolkit: {toolkit_name}\n{description}"
53
+ description = description[:1000]
51
54
  tools.append(BaseAction(
52
55
  api_wrapper=zephyr_api_wrapper,
53
- name=prefix + tool["name"],
54
- description=tool["description"],
56
+ name=tool["name"],
57
+ description=description,
55
58
  args_schema=tool["args_schema"]
56
59
  ))
57
60
  return cls(tools=tools)