alita-sdk 0.3.257__py3-none-any.whl → 0.3.562__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 (278) 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 +1073 -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 +72 -12
  30. alita_sdk/community/inventory/__init__.py +236 -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/toolkit_utils.py +176 -0
  58. alita_sdk/community/inventory/visualize.py +1370 -0
  59. alita_sdk/configurations/__init__.py +11 -0
  60. alita_sdk/configurations/ado.py +148 -2
  61. alita_sdk/configurations/azure_search.py +1 -1
  62. alita_sdk/configurations/bigquery.py +1 -1
  63. alita_sdk/configurations/bitbucket.py +94 -2
  64. alita_sdk/configurations/browser.py +18 -0
  65. alita_sdk/configurations/carrier.py +19 -0
  66. alita_sdk/configurations/confluence.py +130 -1
  67. alita_sdk/configurations/delta_lake.py +1 -1
  68. alita_sdk/configurations/figma.py +76 -5
  69. alita_sdk/configurations/github.py +65 -1
  70. alita_sdk/configurations/gitlab.py +81 -0
  71. alita_sdk/configurations/google_places.py +17 -0
  72. alita_sdk/configurations/jira.py +103 -0
  73. alita_sdk/configurations/openapi.py +111 -0
  74. alita_sdk/configurations/postman.py +1 -1
  75. alita_sdk/configurations/qtest.py +72 -3
  76. alita_sdk/configurations/report_portal.py +115 -0
  77. alita_sdk/configurations/salesforce.py +19 -0
  78. alita_sdk/configurations/service_now.py +1 -12
  79. alita_sdk/configurations/sharepoint.py +167 -0
  80. alita_sdk/configurations/sonar.py +18 -0
  81. alita_sdk/configurations/sql.py +20 -0
  82. alita_sdk/configurations/testio.py +101 -0
  83. alita_sdk/configurations/testrail.py +88 -0
  84. alita_sdk/configurations/xray.py +94 -1
  85. alita_sdk/configurations/zephyr_enterprise.py +94 -1
  86. alita_sdk/configurations/zephyr_essential.py +95 -0
  87. alita_sdk/runtime/clients/artifact.py +21 -4
  88. alita_sdk/runtime/clients/client.py +458 -67
  89. alita_sdk/runtime/clients/mcp_discovery.py +342 -0
  90. alita_sdk/runtime/clients/mcp_manager.py +262 -0
  91. alita_sdk/runtime/clients/sandbox_client.py +352 -0
  92. alita_sdk/runtime/langchain/_constants_bkup.py +1318 -0
  93. alita_sdk/runtime/langchain/assistant.py +183 -43
  94. alita_sdk/runtime/langchain/constants.py +647 -1
  95. alita_sdk/runtime/langchain/document_loaders/AlitaDocxMammothLoader.py +315 -3
  96. alita_sdk/runtime/langchain/document_loaders/AlitaExcelLoader.py +209 -31
  97. alita_sdk/runtime/langchain/document_loaders/AlitaImageLoader.py +1 -1
  98. alita_sdk/runtime/langchain/document_loaders/AlitaJSONLinesLoader.py +77 -0
  99. alita_sdk/runtime/langchain/document_loaders/AlitaJSONLoader.py +10 -3
  100. alita_sdk/runtime/langchain/document_loaders/AlitaMarkdownLoader.py +66 -0
  101. alita_sdk/runtime/langchain/document_loaders/AlitaPDFLoader.py +79 -10
  102. alita_sdk/runtime/langchain/document_loaders/AlitaPowerPointLoader.py +52 -15
  103. alita_sdk/runtime/langchain/document_loaders/AlitaPythonLoader.py +9 -0
  104. alita_sdk/runtime/langchain/document_loaders/AlitaTableLoader.py +1 -4
  105. alita_sdk/runtime/langchain/document_loaders/AlitaTextLoader.py +15 -2
  106. alita_sdk/runtime/langchain/document_loaders/ImageParser.py +30 -0
  107. alita_sdk/runtime/langchain/document_loaders/constants.py +189 -41
  108. alita_sdk/runtime/langchain/interfaces/llm_processor.py +4 -2
  109. alita_sdk/runtime/langchain/langraph_agent.py +407 -92
  110. alita_sdk/runtime/langchain/utils.py +102 -8
  111. alita_sdk/runtime/llms/preloaded.py +2 -6
  112. alita_sdk/runtime/models/mcp_models.py +61 -0
  113. alita_sdk/runtime/skills/__init__.py +91 -0
  114. alita_sdk/runtime/skills/callbacks.py +498 -0
  115. alita_sdk/runtime/skills/discovery.py +540 -0
  116. alita_sdk/runtime/skills/executor.py +610 -0
  117. alita_sdk/runtime/skills/input_builder.py +371 -0
  118. alita_sdk/runtime/skills/models.py +330 -0
  119. alita_sdk/runtime/skills/registry.py +355 -0
  120. alita_sdk/runtime/skills/skill_runner.py +330 -0
  121. alita_sdk/runtime/toolkits/__init__.py +28 -0
  122. alita_sdk/runtime/toolkits/application.py +14 -4
  123. alita_sdk/runtime/toolkits/artifact.py +24 -9
  124. alita_sdk/runtime/toolkits/datasource.py +13 -6
  125. alita_sdk/runtime/toolkits/mcp.py +780 -0
  126. alita_sdk/runtime/toolkits/planning.py +178 -0
  127. alita_sdk/runtime/toolkits/skill_router.py +238 -0
  128. alita_sdk/runtime/toolkits/subgraph.py +11 -6
  129. alita_sdk/runtime/toolkits/tools.py +314 -70
  130. alita_sdk/runtime/toolkits/vectorstore.py +11 -5
  131. alita_sdk/runtime/tools/__init__.py +24 -0
  132. alita_sdk/runtime/tools/application.py +16 -4
  133. alita_sdk/runtime/tools/artifact.py +367 -33
  134. alita_sdk/runtime/tools/data_analysis.py +183 -0
  135. alita_sdk/runtime/tools/function.py +100 -4
  136. alita_sdk/runtime/tools/graph.py +81 -0
  137. alita_sdk/runtime/tools/image_generation.py +218 -0
  138. alita_sdk/runtime/tools/llm.py +1013 -177
  139. alita_sdk/runtime/tools/loop.py +3 -1
  140. alita_sdk/runtime/tools/loop_output.py +3 -1
  141. alita_sdk/runtime/tools/mcp_inspect_tool.py +284 -0
  142. alita_sdk/runtime/tools/mcp_remote_tool.py +181 -0
  143. alita_sdk/runtime/tools/mcp_server_tool.py +3 -1
  144. alita_sdk/runtime/tools/planning/__init__.py +36 -0
  145. alita_sdk/runtime/tools/planning/models.py +246 -0
  146. alita_sdk/runtime/tools/planning/wrapper.py +607 -0
  147. alita_sdk/runtime/tools/router.py +2 -1
  148. alita_sdk/runtime/tools/sandbox.py +375 -0
  149. alita_sdk/runtime/tools/skill_router.py +776 -0
  150. alita_sdk/runtime/tools/tool.py +3 -1
  151. alita_sdk/runtime/tools/vectorstore.py +69 -65
  152. alita_sdk/runtime/tools/vectorstore_base.py +163 -90
  153. alita_sdk/runtime/utils/AlitaCallback.py +137 -21
  154. alita_sdk/runtime/utils/mcp_client.py +492 -0
  155. alita_sdk/runtime/utils/mcp_oauth.py +361 -0
  156. alita_sdk/runtime/utils/mcp_sse_client.py +434 -0
  157. alita_sdk/runtime/utils/mcp_tools_discovery.py +124 -0
  158. alita_sdk/runtime/utils/streamlit.py +41 -14
  159. alita_sdk/runtime/utils/toolkit_utils.py +28 -9
  160. alita_sdk/runtime/utils/utils.py +48 -0
  161. alita_sdk/tools/__init__.py +135 -37
  162. alita_sdk/tools/ado/__init__.py +2 -2
  163. alita_sdk/tools/ado/repos/__init__.py +15 -19
  164. alita_sdk/tools/ado/repos/repos_wrapper.py +12 -20
  165. alita_sdk/tools/ado/test_plan/__init__.py +26 -8
  166. alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +56 -28
  167. alita_sdk/tools/ado/wiki/__init__.py +27 -12
  168. alita_sdk/tools/ado/wiki/ado_wrapper.py +114 -40
  169. alita_sdk/tools/ado/work_item/__init__.py +27 -12
  170. alita_sdk/tools/ado/work_item/ado_wrapper.py +95 -11
  171. alita_sdk/tools/advanced_jira_mining/__init__.py +12 -8
  172. alita_sdk/tools/aws/delta_lake/__init__.py +14 -11
  173. alita_sdk/tools/aws/delta_lake/tool.py +5 -1
  174. alita_sdk/tools/azure_ai/search/__init__.py +13 -8
  175. alita_sdk/tools/base/tool.py +5 -1
  176. alita_sdk/tools/base_indexer_toolkit.py +454 -110
  177. alita_sdk/tools/bitbucket/__init__.py +27 -19
  178. alita_sdk/tools/bitbucket/api_wrapper.py +285 -27
  179. alita_sdk/tools/bitbucket/cloud_api_wrapper.py +5 -5
  180. alita_sdk/tools/browser/__init__.py +41 -16
  181. alita_sdk/tools/browser/crawler.py +3 -1
  182. alita_sdk/tools/browser/utils.py +15 -6
  183. alita_sdk/tools/carrier/__init__.py +18 -17
  184. alita_sdk/tools/carrier/backend_reports_tool.py +8 -4
  185. alita_sdk/tools/carrier/excel_reporter.py +8 -4
  186. alita_sdk/tools/chunkers/__init__.py +3 -1
  187. alita_sdk/tools/chunkers/code/codeparser.py +1 -1
  188. alita_sdk/tools/chunkers/sematic/json_chunker.py +2 -1
  189. alita_sdk/tools/chunkers/sematic/markdown_chunker.py +97 -6
  190. alita_sdk/tools/chunkers/sematic/proposal_chunker.py +1 -1
  191. alita_sdk/tools/chunkers/universal_chunker.py +270 -0
  192. alita_sdk/tools/cloud/aws/__init__.py +11 -7
  193. alita_sdk/tools/cloud/azure/__init__.py +11 -7
  194. alita_sdk/tools/cloud/gcp/__init__.py +11 -7
  195. alita_sdk/tools/cloud/k8s/__init__.py +11 -7
  196. alita_sdk/tools/code/linter/__init__.py +9 -8
  197. alita_sdk/tools/code/loaders/codesearcher.py +3 -2
  198. alita_sdk/tools/code/sonar/__init__.py +20 -13
  199. alita_sdk/tools/code_indexer_toolkit.py +199 -0
  200. alita_sdk/tools/confluence/__init__.py +21 -14
  201. alita_sdk/tools/confluence/api_wrapper.py +197 -58
  202. alita_sdk/tools/confluence/loader.py +14 -2
  203. alita_sdk/tools/custom_open_api/__init__.py +11 -5
  204. alita_sdk/tools/elastic/__init__.py +10 -8
  205. alita_sdk/tools/elitea_base.py +546 -64
  206. alita_sdk/tools/figma/__init__.py +11 -8
  207. alita_sdk/tools/figma/api_wrapper.py +352 -153
  208. alita_sdk/tools/github/__init__.py +17 -17
  209. alita_sdk/tools/github/api_wrapper.py +9 -26
  210. alita_sdk/tools/github/github_client.py +81 -12
  211. alita_sdk/tools/github/schemas.py +2 -1
  212. alita_sdk/tools/github/tool.py +5 -1
  213. alita_sdk/tools/gitlab/__init__.py +18 -13
  214. alita_sdk/tools/gitlab/api_wrapper.py +224 -80
  215. alita_sdk/tools/gitlab_org/__init__.py +13 -10
  216. alita_sdk/tools/google/bigquery/__init__.py +13 -13
  217. alita_sdk/tools/google/bigquery/tool.py +5 -1
  218. alita_sdk/tools/google_places/__init__.py +20 -11
  219. alita_sdk/tools/jira/__init__.py +21 -11
  220. alita_sdk/tools/jira/api_wrapper.py +315 -168
  221. alita_sdk/tools/keycloak/__init__.py +10 -8
  222. alita_sdk/tools/localgit/__init__.py +8 -3
  223. alita_sdk/tools/localgit/local_git.py +62 -54
  224. alita_sdk/tools/localgit/tool.py +5 -1
  225. alita_sdk/tools/memory/__init__.py +38 -14
  226. alita_sdk/tools/non_code_indexer_toolkit.py +7 -2
  227. alita_sdk/tools/ocr/__init__.py +10 -8
  228. alita_sdk/tools/openapi/__init__.py +281 -108
  229. alita_sdk/tools/openapi/api_wrapper.py +883 -0
  230. alita_sdk/tools/openapi/tool.py +20 -0
  231. alita_sdk/tools/pandas/__init__.py +18 -11
  232. alita_sdk/tools/pandas/api_wrapper.py +40 -45
  233. alita_sdk/tools/pandas/dataframe/generator/base.py +3 -1
  234. alita_sdk/tools/postman/__init__.py +10 -11
  235. alita_sdk/tools/postman/api_wrapper.py +19 -8
  236. alita_sdk/tools/postman/postman_analysis.py +8 -1
  237. alita_sdk/tools/pptx/__init__.py +10 -10
  238. alita_sdk/tools/qtest/__init__.py +21 -14
  239. alita_sdk/tools/qtest/api_wrapper.py +1784 -88
  240. alita_sdk/tools/rally/__init__.py +12 -10
  241. alita_sdk/tools/report_portal/__init__.py +22 -16
  242. alita_sdk/tools/salesforce/__init__.py +21 -16
  243. alita_sdk/tools/servicenow/__init__.py +20 -16
  244. alita_sdk/tools/servicenow/api_wrapper.py +1 -1
  245. alita_sdk/tools/sharepoint/__init__.py +16 -14
  246. alita_sdk/tools/sharepoint/api_wrapper.py +179 -39
  247. alita_sdk/tools/sharepoint/authorization_helper.py +191 -1
  248. alita_sdk/tools/sharepoint/utils.py +8 -2
  249. alita_sdk/tools/slack/__init__.py +11 -7
  250. alita_sdk/tools/sql/__init__.py +21 -19
  251. alita_sdk/tools/sql/api_wrapper.py +71 -23
  252. alita_sdk/tools/testio/__init__.py +20 -13
  253. alita_sdk/tools/testrail/__init__.py +12 -11
  254. alita_sdk/tools/testrail/api_wrapper.py +214 -46
  255. alita_sdk/tools/utils/__init__.py +28 -4
  256. alita_sdk/tools/utils/content_parser.py +182 -62
  257. alita_sdk/tools/utils/text_operations.py +254 -0
  258. alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +83 -27
  259. alita_sdk/tools/xray/__init__.py +17 -14
  260. alita_sdk/tools/xray/api_wrapper.py +58 -113
  261. alita_sdk/tools/yagmail/__init__.py +8 -3
  262. alita_sdk/tools/zephyr/__init__.py +11 -7
  263. alita_sdk/tools/zephyr_enterprise/__init__.py +15 -9
  264. alita_sdk/tools/zephyr_enterprise/api_wrapper.py +30 -15
  265. alita_sdk/tools/zephyr_essential/__init__.py +15 -10
  266. alita_sdk/tools/zephyr_essential/api_wrapper.py +297 -54
  267. alita_sdk/tools/zephyr_essential/client.py +6 -4
  268. alita_sdk/tools/zephyr_scale/__init__.py +12 -8
  269. alita_sdk/tools/zephyr_scale/api_wrapper.py +39 -31
  270. alita_sdk/tools/zephyr_squad/__init__.py +11 -7
  271. {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.562.dist-info}/METADATA +184 -37
  272. alita_sdk-0.3.562.dist-info/RECORD +450 -0
  273. alita_sdk-0.3.562.dist-info/entry_points.txt +2 -0
  274. alita_sdk/tools/bitbucket/tools.py +0 -304
  275. alita_sdk-0.3.257.dist-info/RECORD +0 -343
  276. {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.562.dist-info}/WHEEL +0 -0
  277. {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.562.dist-info}/licenses/LICENSE +0 -0
  278. {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.562.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  import json
2
2
  import logging
3
3
  import hashlib
4
- from typing import Any, Dict, Generator, List, Optional
4
+ from typing import Any, Dict, Generator, List, Optional, Literal
5
5
 
6
6
  import requests
7
7
  from langchain_core.documents import Document
@@ -9,12 +9,9 @@ from langchain_core.tools import ToolException
9
9
  from pydantic import PrivateAttr, SecretStr, create_model, model_validator, Field
10
10
  from python_graphql_client import GraphqlClient
11
11
 
12
- from ..elitea_base import (
13
- BaseVectorStoreToolApiWrapper,
14
- extend_with_vector_tools,
15
- )
12
+ from ..non_code_indexer_toolkit import NonCodeIndexerToolkit
13
+ from ..utils.available_tools_decorator import extend_with_parent_available_tools
16
14
  from ...runtime.utils.utils import IndexerKeywords
17
- from ..utils.content_parser import parse_file_content, load_content_from_bytes
18
15
 
19
16
  try:
20
17
  from alita_sdk.runtime.langchain.interfaces.llm_processor import get_embeddings
@@ -31,7 +28,7 @@ _get_tests_query = """query GetTests($jql: String!, $limit:Int!, $start: Int)
31
28
  limit
32
29
  results {
33
30
  issueId
34
- jira(fields: ["key", "summary", "created", "updated", "assignee.displayName", "reporter.displayName"])
31
+ jira(fields: ["key", "summary", "description", "created", "updated", "assignee.displayName", "reporter.displayName"])
35
32
  projectId
36
33
  testType {
37
34
  name
@@ -107,7 +104,7 @@ XrayCreateTest = create_model(
107
104
 
108
105
  XrayCreateTests = create_model(
109
106
  "XrayCreateTests",
110
- graphql_mutations=(list[str], Field(description="list of GraphQL mutations:\n" + _graphql_mutation_description))
107
+ graphql_mutations=(List[str], Field(description="list of GraphQL mutations:\n" + _graphql_mutation_description))
111
108
  )
112
109
 
113
110
  def _parse_tests(test_results) -> List[Any]:
@@ -120,7 +117,7 @@ def _parse_tests(test_results) -> List[Any]:
120
117
  return test_results
121
118
 
122
119
 
123
- class XrayApiWrapper(BaseVectorStoreToolApiWrapper):
120
+ class XrayApiWrapper(NonCodeIndexerToolkit):
124
121
  _default_base_url: str = 'https://xray.cloud.getxray.app'
125
122
  base_url: str = ""
126
123
  client_id: str = None
@@ -147,7 +144,7 @@ class XrayApiWrapper(BaseVectorStoreToolApiWrapper):
147
144
  client_id = values['client_id']
148
145
  client_secret = values['client_secret']
149
146
  # Authenticate to get the token
150
- values['base_url'] = values.get('base_url', '') or cls._default_base_url
147
+ values['base_url'] = values.get('base_url', '') or cls._default_base_url.default
151
148
  auth_url = f"{values['base_url']}/api/v1/authenticate"
152
149
  auth_data = {
153
150
  "client_id": client_id,
@@ -168,7 +165,7 @@ class XrayApiWrapper(BaseVectorStoreToolApiWrapper):
168
165
  return ToolException(f"Please, check you credentials ({values['client_id']} / {masked_secret}). Unable")
169
166
  else:
170
167
  return ToolException(f"Authentication failed: {str(e)}")
171
- return values
168
+ return super().validate_toolkit(values)
172
169
 
173
170
  def __init__(self, **data):
174
171
  super().__init__(**data)
@@ -333,6 +330,7 @@ class XrayApiWrapper(BaseVectorStoreToolApiWrapper):
333
330
 
334
331
  for test in tests_data:
335
332
  page_content = ""
333
+ content_structure = {}
336
334
  test_type_name = test.get("testType", {}).get("name", "").lower()
337
335
 
338
336
  attachment_ids = []
@@ -359,19 +357,16 @@ class XrayApiWrapper(BaseVectorStoreToolApiWrapper):
359
357
  content_structure = {"steps": steps_content}
360
358
  if attachment_ids:
361
359
  content_structure["attachment_ids"] = sorted(attachment_ids)
362
- page_content = json.dumps(content_structure, indent=2)
363
360
 
364
361
  elif test_type_name == "cucumber" and test.get("gherkin"):
365
362
  content_structure = {"gherkin": test["gherkin"]}
366
363
  if attachment_ids:
367
364
  content_structure["attachment_ids"] = sorted(attachment_ids)
368
- page_content = json.dumps(content_structure, indent=2)
369
365
 
370
366
  elif test.get("unstructured"):
371
367
  content_structure = {"unstructured": test["unstructured"]}
372
368
  if attachment_ids:
373
369
  content_structure["attachment_ids"] = sorted(attachment_ids)
374
- page_content = json.dumps(content_structure, indent=2)
375
370
 
376
371
  metadata = {"doctype": self.doctype}
377
372
 
@@ -382,7 +377,12 @@ class XrayApiWrapper(BaseVectorStoreToolApiWrapper):
382
377
 
383
378
  if "created" in jira_data:
384
379
  metadata["created_on"] = jira_data["created"]
385
-
380
+
381
+ if jira_data.get("description"):
382
+ content_structure["description"] = jira_data.get("description")
383
+
384
+ page_content = json.dumps(content_structure if content_structure.items() else "", indent=2)
385
+
386
386
  content_hash = hashlib.sha256(page_content.encode('utf-8')).hexdigest()[:16]
387
387
  metadata["updated_on"] = content_hash
388
388
 
@@ -407,11 +407,13 @@ class XrayApiWrapper(BaseVectorStoreToolApiWrapper):
407
407
  if "attachments" in step and step["attachments"]:
408
408
  for attachment in step["attachments"]:
409
409
  if attachment and "id" in attachment and "filename" in attachment:
410
+ attachment['step_id'] = step['id']
410
411
  attachments_data.append(attachment)
411
412
  if attachments_data:
412
413
  metadata["_attachments_data"] = attachments_data
413
414
 
414
- yield Document(page_content=page_content, metadata=metadata)
415
+ metadata[IndexerKeywords.CONTENT_IN_BYTES.value] = page_content.encode('utf-8')
416
+ yield Document(page_content='', metadata=metadata)
415
417
 
416
418
  except Exception as e:
417
419
  logger.error(f"Error processing test data: {e}")
@@ -430,14 +432,7 @@ class XrayApiWrapper(BaseVectorStoreToolApiWrapper):
430
432
  Generator[Document, None, None]: A generator yielding processed Document objects with metadata.
431
433
  """
432
434
  try:
433
- if not getattr(self, '_include_attachments', False):
434
- yield document
435
- return
436
-
437
435
  attachments_data = document.metadata.get("_attachments_data", [])
438
- if not attachments_data:
439
- yield document
440
- return
441
436
 
442
437
  issue_id = document.metadata.get("id")
443
438
 
@@ -458,44 +453,33 @@ class XrayApiWrapper(BaseVectorStoreToolApiWrapper):
458
453
  ).append(attachment_id)
459
454
 
460
455
  try:
461
- content = self._process_attachment(attachment)
462
- if not content or content.startswith("Attachment processing failed"):
463
- logger.warning(f"Skipping attachment {filename} due to processing failure")
464
- continue
456
+ attachment_metadata = {
457
+ 'id': str(attachment_id),
458
+ 'issue_key': document.metadata.get('key', ''),
459
+ 'issueId': str(issue_id),
460
+ 'projectId': document.metadata.get('projectId', ''),
461
+ 'source': f"xray_test_{issue_id}",
462
+ 'filename': filename,
463
+ 'download_link': attachment.get('downloadLink', ''),
464
+ 'entity_type': 'test_case_attachment',
465
+ 'step_id': attachment.get('step_id', ''),
466
+ 'key': document.metadata.get('key', ''),
467
+ IndexerKeywords.PARENT.value: document.metadata.get('id', str(issue_id)),
468
+ 'type': 'attachment',
469
+ 'doctype': self.doctype,
470
+ }
471
+ yield from self._process_attachment(attachment, attachment_metadata)
465
472
  except Exception as e:
466
473
  logger.error(f"Failed to process attachment {filename}: {str(e)}")
467
474
  continue
468
-
469
- attachment_metadata = {
470
- 'id': str(attachment_id),
471
- 'issue_key': document.metadata.get('key', ''),
472
- 'issueId': str(issue_id),
473
- 'projectId': document.metadata.get('projectId', ''),
474
- 'source': f"xray_test_{issue_id}",
475
- 'filename': filename,
476
- 'download_link': attachment.get('downloadLink', ''),
477
- 'entity_type': 'test_case_attachment',
478
- 'key': document.metadata.get('key', ''),
479
- IndexerKeywords.PARENT.value: document.metadata.get('id', str(issue_id)),
480
- 'type': 'attachment',
481
- 'doctype': self.doctype,
482
- }
483
-
484
- yield Document(
485
- page_content=content,
486
- metadata=attachment_metadata
487
- )
488
475
 
489
476
  if "_attachments_data" in document.metadata:
490
477
  del document.metadata["_attachments_data"]
491
478
 
492
- yield document
493
-
494
479
  except Exception as e:
495
480
  logger.error(f"Error processing document for attachments: {e}")
496
- yield document
497
481
 
498
- def _process_attachment(self, attachment: Dict[str, Any]) -> str:
482
+ def _process_attachment(self, attachment: Dict[str, Any], attachment_metadata) -> Generator[Document, None, None]:
499
483
  """
500
484
  Processes an attachment to extract its content.
501
485
 
@@ -508,38 +492,17 @@ class XrayApiWrapper(BaseVectorStoreToolApiWrapper):
508
492
  try:
509
493
  download_link = attachment.get('downloadLink')
510
494
  filename = attachment.get('filename', '')
511
-
512
- if not download_link:
513
- return f"Attachment: {filename} (no download link available)"
514
495
 
515
496
  try:
516
497
  auth_token = self._ensure_auth_token()
517
498
  headers = {'Authorization': f'Bearer {auth_token}'}
518
499
  response = requests.get(download_link, headers=headers, timeout=30)
519
500
  response.raise_for_status()
520
-
521
- ext = f".{filename.split('.')[-1].lower()}" if filename and '.' in filename else ""
522
-
523
- if ext == '.pdf':
524
- content = parse_file_content(
525
- file_content=response.content,
526
- file_name=filename,
527
- llm=self.llm,
528
- is_capture_image=True
529
- )
530
- else:
531
- content = load_content_from_bytes(
532
- response.content,
533
- ext,
534
- llm=self.llm
535
- )
536
-
537
- if content:
538
- return f"filename: {filename}\ncontent: {content}"
539
- else:
540
- logger.warning(f"No content extracted from attachment {filename}")
541
- return f"filename: {filename}\ncontent: [No extractable content]"
542
-
501
+
502
+ yield from self._load_attachment(content=response.content,
503
+ file_name=filename,
504
+ attachment_metadata=attachment_metadata)
505
+
543
506
  except requests.RequestException as req_e:
544
507
  logger.error(f"Unable to download attachment {filename} with existing token: {req_e}")
545
508
 
@@ -560,23 +523,13 @@ class XrayApiWrapper(BaseVectorStoreToolApiWrapper):
560
523
  fresh_headers = {'Authorization': f'Bearer {fresh_token}'}
561
524
  response = requests.get(download_link, headers=fresh_headers, timeout=60)
562
525
  response.raise_for_status()
563
-
564
- ext = f".{filename.split('.')[-1].lower()}" if filename and '.' in filename else ""
565
- content = parse_file_content(
566
- file_content=response.content,
567
- file_name=filename,
568
- llm=self.llm,
569
- is_capture_image=True
570
- ) if ext == '.pdf' else load_content_from_bytes(response.content, ext, llm=self.llm)
571
-
572
- if content:
573
- return f"filename: {filename}\ncontent: {content}"
574
- else:
575
- return f"filename: {filename}\ncontent: [Content extraction failed after re-auth]"
526
+
527
+ yield from self._load_attachment(content=response.content,
528
+ file_name=filename,
529
+ attachment_metadata=attachment_metadata)
576
530
 
577
531
  except Exception as reauth_e:
578
532
  logger.error(f"Re-authentication and retry failed for {filename}: {reauth_e}")
579
- return f"Attachment: {filename} (download failed: {str(req_e)}, re-auth failed: {str(reauth_e)})"
580
533
  else:
581
534
  try:
582
535
  auth_token = self._ensure_auth_token()
@@ -587,34 +540,29 @@ class XrayApiWrapper(BaseVectorStoreToolApiWrapper):
587
540
  }
588
541
  response = requests.get(download_link, headers=fallback_headers, timeout=60)
589
542
  response.raise_for_status()
590
-
591
- ext = f".{filename.split('.')[-1].lower()}" if filename and '.' in filename else ""
592
- content = parse_file_content(
593
- file_content=response.content,
594
- file_name=filename,
595
- llm=self.llm,
596
- is_capture_image=True
597
- ) if ext == '.pdf' else load_content_from_bytes(response.content, ext, llm=self.llm)
598
-
599
- if content:
600
- return f"filename: {filename}\ncontent: {content}"
601
- else:
602
- return f"filename: {filename}\ncontent: [Content extraction failed after fallback]"
543
+
544
+ yield from self._load_attachment(content=response.content,
545
+ file_name=filename,
546
+ attachment_metadata=attachment_metadata)
603
547
 
604
548
  except Exception as fallback_e:
605
549
  logger.error(f"Fallback download also failed for {filename}: {fallback_e}")
606
- return f"Attachment: {filename} (download failed: {str(req_e)}, fallback failed: {str(fallback_e)})"
607
550
 
608
551
  except Exception as parse_e:
609
552
  logger.error(f"Unable to parse attachment {filename}: {parse_e}")
610
- return f"Attachment: {filename} (parsing failed: {str(parse_e)})"
611
553
 
612
554
  except Exception as e:
613
555
  logger.error(f"Error processing attachment: {e}")
614
- return f"Attachment processing failed: {str(e)}"
556
+
557
+ def _load_attachment(self, content, file_name, attachment_metadata) -> Generator[Document, None, None]:
558
+ attachment_metadata[IndexerKeywords.CONTENT_IN_BYTES.value] = content
559
+ attachment_metadata[IndexerKeywords.CONTENT_FILE_NAME.value] = file_name
560
+ yield Document(page_content='', metadata=attachment_metadata)
615
561
 
616
562
  def _index_tool_params(self, **kwargs) -> dict[str, tuple[type, Field]]:
617
563
  return {
564
+ 'chunking_tool': (Literal['json', ''],
565
+ Field(description="Name of chunking tool for base document", default='json')),
618
566
  'jql': (Optional[str], Field(description="""JQL query for searching test cases in Xray.
619
567
 
620
568
  Standard JQL query syntax for filtering Xray test cases. Examples:
@@ -684,9 +632,9 @@ class XrayApiWrapper(BaseVectorStoreToolApiWrapper):
684
632
  except Exception as e:
685
633
  raise ToolException(f"Unable to execute GraphQL due to error: {str(e)}")
686
634
 
687
- @extend_with_vector_tools
635
+ @extend_with_parent_available_tools
688
636
  def get_available_tools(self):
689
- tools = [
637
+ return [
690
638
  {
691
639
  "name": "get_tests",
692
640
  "description": self.get_tests.__doc__,
@@ -711,7 +659,4 @@ class XrayApiWrapper(BaseVectorStoreToolApiWrapper):
711
659
  "args_schema": XrayGrapql,
712
660
  "ref": self.execute_graphql,
713
661
  }
714
- ]
715
-
716
- tools.extend(self._get_vector_search_tools())
717
- return tools
662
+ ]
@@ -34,7 +34,7 @@ class AlitaYagmailToolkit(BaseToolkit):
34
34
  )
35
35
 
36
36
  @classmethod
37
- def get_toolkit(cls, selected_tools: list[str] | None = None, **kwargs):
37
+ def get_toolkit(cls, selected_tools: list[str] | None = None, toolkit_name: Optional[str] = None, **kwargs):
38
38
  if selected_tools is None:
39
39
  selected_tools = []
40
40
  yagmail_wrapper = YagmailWrapper(**kwargs)
@@ -44,11 +44,16 @@ class AlitaYagmailToolkit(BaseToolkit):
44
44
  if selected_tools:
45
45
  if tool["name"] not in selected_tools:
46
46
  continue
47
+ description = tool["description"]
48
+ if toolkit_name:
49
+ description = f"Toolkit: {toolkit_name}\n{description}"
50
+ description = description[:1000]
47
51
  tools.append(BaseAction(
48
52
  api_wrapper=yagmail_wrapper,
49
53
  name=tool["name"],
50
- description=tool["description"],
51
- args_schema=tool["args_schema"]
54
+ description=description,
55
+ args_schema=tool["args_schema"],
56
+ metadata={"toolkit_name": toolkit_name} if toolkit_name else {}
52
57
  ))
53
58
  return cls(tools=tools)
54
59
 
@@ -7,7 +7,8 @@ from pydantic import create_model, BaseModel, Field, SecretStr
7
7
 
8
8
  from ..base.tool import BaseAction
9
9
  from .api_wrapper import ZephyrV1ApiWrapper
10
- from ..utils import clean_string, TOOLKIT_SPLITTER, get_max_toolkit_length
10
+ from ..elitea_base import filter_missconfigured_index_tools
11
+ from ..utils import clean_string, get_max_toolkit_length
11
12
 
12
13
  name = "zephyr"
13
14
 
@@ -22,15 +23,13 @@ def get_tools(tool):
22
23
 
23
24
  class ZephyrToolkit(BaseToolkit):
24
25
  tools: List[BaseTool] = []
25
- toolkit_max_length: int = 0
26
26
 
27
27
  @staticmethod
28
28
  def toolkit_config_schema() -> BaseModel:
29
29
  selected_tools = {x['name']: x['args_schema'].schema() for x in ZephyrV1ApiWrapper.model_construct().get_available_tools()}
30
- ZephyrToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
31
30
  return create_model(
32
31
  name,
33
- base_url=(str, Field(description="Base URL", json_schema_extra={'toolkit_name': True, 'max_toolkit_length': ZephyrToolkit.toolkit_max_length})),
32
+ base_url=(str, Field(description="Base URL")),
34
33
  username=(str, Field(description="Username")),
35
34
  password=(SecretStr, Field(description="Password", json_schema_extra={'secret': True})),
36
35
  selected_tools=(List[Literal[tuple(selected_tools)]], Field(default=[], json_schema_extra={'args_schemas': selected_tools})),
@@ -45,20 +44,25 @@ class ZephyrToolkit(BaseToolkit):
45
44
  )
46
45
 
47
46
  @classmethod
47
+ @filter_missconfigured_index_tools
48
48
  def get_toolkit(cls, selected_tools: list[str] | None = None, toolkit_name: Optional[str] = None, **kwargs):
49
49
  zephyr_api_wrapper = ZephyrV1ApiWrapper(**kwargs)
50
- prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
51
50
  available_tools = zephyr_api_wrapper.get_available_tools()
52
51
  tools = []
53
52
  for tool in available_tools:
54
53
  if selected_tools:
55
54
  if tool["name"] not in selected_tools:
56
55
  continue
56
+ description = tool["description"]
57
+ if toolkit_name:
58
+ description = f"Toolkit: {toolkit_name}\n{description}"
59
+ description = description[:1000]
57
60
  tools.append(BaseAction(
58
61
  api_wrapper=zephyr_api_wrapper,
59
62
  name=tool["name"],
60
- description=tool["description"],
61
- args_schema=tool["args_schema"]
63
+ description=description,
64
+ args_schema=tool["args_schema"],
65
+ metadata={"toolkit_name": toolkit_name} if toolkit_name else {}
62
66
  ))
63
67
  return cls(tools=tools)
64
68
 
@@ -4,7 +4,8 @@ from typing import List, Literal, Optional
4
4
 
5
5
  from .api_wrapper import ZephyrApiWrapper
6
6
  from ..base.tool import BaseAction
7
- from ..utils import clean_string, get_max_toolkit_length, TOOLKIT_SPLITTER
7
+ from ..elitea_base import filter_missconfigured_index_tools
8
+ from ..utils import clean_string, get_max_toolkit_length
8
9
  from ...configurations.pgvector import PgVectorConfiguration
9
10
  from ...configurations.zephyr_enterprise import ZephyrEnterpriseConfiguration
10
11
 
@@ -27,23 +28,22 @@ def get_tools(tool):
27
28
 
28
29
  class ZephyrEnterpriseToolkit(BaseToolkit):
29
30
  tools: List[BaseTool] = []
30
- toolkit_max_length: int = 0
31
31
 
32
32
  @staticmethod
33
33
  def toolkit_config_schema() -> BaseModel:
34
34
  selected_tools = {x['name']: x['args_schema'].schema() for x in
35
35
  ZephyrApiWrapper.model_construct().get_available_tools()}
36
- ZephyrEnterpriseToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
37
36
  return create_model(
38
37
  name,
39
- zephyr_configuration=(Optional[ZephyrEnterpriseConfiguration], Field(description="Zephyr Configuration", json_schema_extra={'configuration_types': ['zephyr-enterprise']})),
38
+ zephyr_configuration=(ZephyrEnterpriseConfiguration, Field(description="Zephyr Configuration", json_schema_extra={'configuration_types': ['zephyr_enterprise']})),
40
39
  pgvector_configuration=(Optional[PgVectorConfiguration], Field(description="PgVector Configuration",
41
40
  json_schema_extra={
42
41
  'configuration_types': ['pgvector']},
43
42
  default=None)),
44
43
  # embedder settings
45
44
  embedding_model=(Optional[str], Field(default=None, description="Embedding configuration.", json_schema_extra={'configuration_model': 'embedding'})),
46
- selected_tools=(List[Literal[tuple(selected_tools)]], []),
45
+ selected_tools=(List[Literal[tuple(selected_tools)]],
46
+ Field(default=[], json_schema_extra={'args_schemas': selected_tools})),
47
47
  __config__=ConfigDict(json_schema_extra={
48
48
  'metadata': {
49
49
  "label": "Zephyr Enterprise", "icon_url": "zephyr.svg",
@@ -53,6 +53,7 @@ class ZephyrEnterpriseToolkit(BaseToolkit):
53
53
  )
54
54
 
55
55
  @classmethod
56
+ @filter_missconfigured_index_tools
56
57
  def get_toolkit(cls, selected_tools: list[str] | None = None, toolkit_name: Optional[str] = None, **kwargs):
57
58
  if selected_tools is None:
58
59
  selected_tools = []
@@ -64,17 +65,22 @@ class ZephyrEnterpriseToolkit(BaseToolkit):
64
65
  **(kwargs.get('embedding_configuration') or {}),
65
66
  }
66
67
  zephyr_api_wrapper = ZephyrApiWrapper(**wrapper_payload)
67
- prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
68
68
  available_tools = zephyr_api_wrapper.get_available_tools()
69
69
  tools = []
70
70
  for tool in available_tools:
71
71
  if selected_tools and tool["name"] not in selected_tools:
72
72
  continue
73
+ description = tool["description"]
74
+ if toolkit_name:
75
+ description = f"Toolkit: {toolkit_name}\n{description}"
76
+ description = description + "\nZephyr Enterprise instance: " + zephyr_api_wrapper.base_url
77
+ description = description[:1000]
73
78
  tools.append(BaseAction(
74
79
  api_wrapper=zephyr_api_wrapper,
75
- name=prefix + tool["name"],
76
- description=tool["description"] + "\nZephyr Enterprise instance: " + zephyr_api_wrapper.base_url,
77
- args_schema=tool["args_schema"]
80
+ name=tool["name"],
81
+ description=description,
82
+ args_schema=tool["args_schema"],
83
+ metadata={"toolkit_name": toolkit_name} if toolkit_name else {}
78
84
  ))
79
85
  return cls(tools=tools)
80
86
 
@@ -1,14 +1,16 @@
1
+ import json
1
2
  import logging
2
- from importlib.metadata import metadata
3
- from operator import ifloordiv
4
- from typing import Optional, List, Generator
3
+ from typing import Optional, List, Generator, Literal
5
4
 
6
5
  from langchain_core.tools import ToolException
7
6
  from pydantic import create_model, model_validator, PrivateAttr, Field, SecretStr
8
7
 
9
8
  from langchain_core.documents import Document
10
9
  from .zephyr_enterprise import ZephyrClient
11
- from ..elitea_base import BaseToolApiWrapper, BaseVectorStoreToolApiWrapper, extend_with_vector_tools
10
+ from ..non_code_indexer_toolkit import NonCodeIndexerToolkit
11
+ from ..utils.available_tools_decorator import extend_with_parent_available_tools
12
+ from ..utils.content_parser import file_extension_by_chunker
13
+ from ...runtime.utils.utils import IndexerKeywords
12
14
 
13
15
  logger = logging.getLogger(__name__)
14
16
 
@@ -23,7 +25,7 @@ zql_description = """
23
25
  "folder=\"TestToolkit\"", "name~\"TestToolkit5\"
24
26
  """
25
27
 
26
- class ZephyrApiWrapper(BaseVectorStoreToolApiWrapper):
28
+ class ZephyrApiWrapper(NonCodeIndexerToolkit):
27
29
  base_url: str
28
30
  token: SecretStr
29
31
  _client: Optional[ZephyrClient] = PrivateAttr()
@@ -34,7 +36,7 @@ class ZephyrApiWrapper(BaseVectorStoreToolApiWrapper):
34
36
  base_url = values.get('base_url')
35
37
  token = values.get('token')
36
38
  cls._client = ZephyrClient(base_url=base_url, token=token)
37
- return values
39
+ return super().validate_toolkit(values)
38
40
 
39
41
  def get_test_case(self, testcase_id: str):
40
42
 
@@ -153,25 +155,38 @@ class ZephyrApiWrapper(BaseVectorStoreToolApiWrapper):
153
155
  Returns a list of fields for index_data args schema.
154
156
  """
155
157
  return {
158
+ 'chunking_tool': (Literal['json', ''], Field(description="Name of chunking tool", default='json')),
156
159
  "zql": (str, Field(description=zql_description, examples=["folder=\"TestToolkit\"", "name~\"TestToolkit5\""]))
160
+
157
161
  }
158
162
 
159
163
  def _base_loader(self, zql: str, **kwargs) -> Generator[Document, None, None]:
160
- test_cases = self.get_testcases_by_zql(zql)
164
+ self._chunking_tool = kwargs.get('chunking_tool', None)
165
+ test_cases = self.get_testcases_by_zql(zql=zql, return_as_list=True)
161
166
  for test_case in test_cases:
162
167
  metadata = {
163
- ("updated_on" if k == "lastModifiedOn" else "id" if k == "testcaseId" else k): str(v)
164
- for k, v in test_case
165
- if k != "id"
168
+ "updated_on": str(test_case.get("lastModifiedOn")),
169
+ "id": str(test_case.get("id")),
170
+ "name": test_case.get("name"),
171
+ "testcaseId": str(test_case.get("testcaseId")),
172
+ "projectId": test_case.get("projectId"),
173
+ "projectName": test_case.get("projectName"),
174
+ "testcaseType": test_case.get("testcaseType"),
166
175
  }
167
176
  yield Document(page_content='', metadata=metadata)
168
177
 
169
- def _process_document(self, document: Document) -> Generator[Document, None, None]:
170
- id = document.metadata['id']
171
- test_case_content = self.get_test_case_steps(id)
172
- document.page_content = test_case_content
178
+ def _extend_data(self, documents: Generator[Document, None, None]) -> Generator[Document, None, None]:
179
+ for document in documents:
180
+ try:
181
+ id = document.metadata['id']
182
+ test_case_content = self.get_test_case_steps(id)
183
+ page_content = json.dumps(test_case_content)
184
+ document.metadata[IndexerKeywords.CONTENT_IN_BYTES.value] = page_content.encode('utf-8')
185
+ except Exception as e:
186
+ logging.error(f"Failed to process document: {e}")
187
+ yield document
173
188
 
174
- @extend_with_vector_tools
189
+ @extend_with_parent_available_tools
175
190
  def get_available_tools(self):
176
191
  return [
177
192
  {
@@ -5,15 +5,17 @@ from pydantic import create_model, BaseModel, Field
5
5
 
6
6
  from .api_wrapper import ZephyrEssentialApiWrapper
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
  from ...configurations.pgvector import PgVectorConfiguration
11
+ from ...configurations.zephyr_essential import ZephyrEssentialConfiguration
10
12
 
11
13
  name = "zephyr_essential"
12
14
 
13
15
  def get_tools(tool):
14
16
  return ZephyrEssentialToolkit().get_toolkit(
15
17
  selected_tools=tool['settings'].get('selected_tools', []),
16
- token=tool['settings']["token"],
18
+ zephyr_essential_configuration=tool['settings']['zephyr_essential_configuration'],
17
19
  toolkit_name=tool.get('toolkit_name'),
18
20
  llm = tool['settings'].get('llm', None),
19
21
  alita=tool['settings'].get('alita', None),
@@ -27,16 +29,13 @@ def get_tools(tool):
27
29
 
28
30
  class ZephyrEssentialToolkit(BaseToolkit):
29
31
  tools: List[BaseTool] = []
30
- toolkit_max_length: int = 0
31
32
 
32
33
  @staticmethod
33
34
  def toolkit_config_schema() -> BaseModel:
34
35
  selected_tools = {x['name']: x['args_schema'].schema() for x in ZephyrEssentialApiWrapper.model_construct().get_available_tools()}
35
- ZephyrEssentialToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
36
36
  return create_model(
37
37
  name,
38
- token=(str, Field(description="Bearer api token")),
39
- base_url=(Optional[str], Field(description="Zephyr Essential base url", default=None)),
38
+ zephyr_essential_configuration=(ZephyrEssentialConfiguration, Field(description="Zephyr Essential Configuration", json_schema_extra={'configuration_types': ['zephyr_essential']})),
40
39
  selected_tools=(List[Literal[tuple(selected_tools)]], Field(default=[], json_schema_extra={'args_schemas': selected_tools})),
41
40
  pgvector_configuration=(Optional[PgVectorConfiguration], Field(default=None,
42
41
  description="PgVector Configuration",
@@ -51,26 +50,32 @@ class ZephyrEssentialToolkit(BaseToolkit):
51
50
  )
52
51
 
53
52
  @classmethod
53
+ @filter_missconfigured_index_tools
54
54
  def get_toolkit(cls, selected_tools: list[str] | None = None, toolkit_name: Optional[str] = None, **kwargs):
55
55
  if selected_tools is None:
56
56
  selected_tools = []
57
57
  wrapper_payload = {
58
58
  **kwargs,
59
+ **kwargs.get('zephyr_essential_configuration', {}),
59
60
  **(kwargs.get('pgvector_configuration') or {}),
60
61
  }
61
62
  zephyr_api_wrapper = ZephyrEssentialApiWrapper(**wrapper_payload)
62
- prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
63
63
  available_tools = zephyr_api_wrapper.get_available_tools()
64
64
  tools = []
65
65
  for tool in available_tools:
66
66
  if selected_tools:
67
67
  if tool["name"] not in selected_tools:
68
68
  continue
69
+ description = tool["description"]
70
+ if toolkit_name:
71
+ description = f"Toolkit: {toolkit_name}\n{description}"
72
+ description = description[:1000]
69
73
  tools.append(BaseAction(
70
74
  api_wrapper=zephyr_api_wrapper,
71
- name=prefix + tool["name"],
72
- description=tool["description"],
73
- args_schema=tool["args_schema"]
75
+ name=tool["name"],
76
+ description=description,
77
+ args_schema=tool["args_schema"],
78
+ metadata={"toolkit_name": toolkit_name} if toolkit_name else {}
74
79
  ))
75
80
  return cls(tools=tools)
76
81