alita-sdk 0.3.257__py3-none-any.whl → 0.3.584__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.

Potentially problematic release.


This version of alita-sdk might be problematic. Click here for more details.

Files changed (281) 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 +3794 -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 +323 -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 +493 -105
  110. alita_sdk/runtime/langchain/utils.py +118 -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 +25 -9
  124. alita_sdk/runtime/toolkits/datasource.py +13 -6
  125. alita_sdk/runtime/toolkits/mcp.py +782 -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 +1032 -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/constants.py +5 -1
  155. alita_sdk/runtime/utils/mcp_client.py +492 -0
  156. alita_sdk/runtime/utils/mcp_oauth.py +361 -0
  157. alita_sdk/runtime/utils/mcp_sse_client.py +434 -0
  158. alita_sdk/runtime/utils/mcp_tools_discovery.py +124 -0
  159. alita_sdk/runtime/utils/streamlit.py +41 -14
  160. alita_sdk/runtime/utils/toolkit_utils.py +28 -9
  161. alita_sdk/runtime/utils/utils.py +48 -0
  162. alita_sdk/tools/__init__.py +135 -37
  163. alita_sdk/tools/ado/__init__.py +2 -2
  164. alita_sdk/tools/ado/repos/__init__.py +16 -19
  165. alita_sdk/tools/ado/repos/repos_wrapper.py +12 -20
  166. alita_sdk/tools/ado/test_plan/__init__.py +27 -8
  167. alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +56 -28
  168. alita_sdk/tools/ado/wiki/__init__.py +28 -12
  169. alita_sdk/tools/ado/wiki/ado_wrapper.py +114 -40
  170. alita_sdk/tools/ado/work_item/__init__.py +28 -12
  171. alita_sdk/tools/ado/work_item/ado_wrapper.py +95 -11
  172. alita_sdk/tools/advanced_jira_mining/__init__.py +13 -8
  173. alita_sdk/tools/aws/delta_lake/__init__.py +15 -11
  174. alita_sdk/tools/aws/delta_lake/tool.py +5 -1
  175. alita_sdk/tools/azure_ai/search/__init__.py +14 -8
  176. alita_sdk/tools/base/tool.py +5 -1
  177. alita_sdk/tools/base_indexer_toolkit.py +454 -110
  178. alita_sdk/tools/bitbucket/__init__.py +28 -19
  179. alita_sdk/tools/bitbucket/api_wrapper.py +285 -27
  180. alita_sdk/tools/bitbucket/cloud_api_wrapper.py +5 -5
  181. alita_sdk/tools/browser/__init__.py +41 -16
  182. alita_sdk/tools/browser/crawler.py +3 -1
  183. alita_sdk/tools/browser/utils.py +15 -6
  184. alita_sdk/tools/carrier/__init__.py +18 -17
  185. alita_sdk/tools/carrier/backend_reports_tool.py +8 -4
  186. alita_sdk/tools/carrier/excel_reporter.py +8 -4
  187. alita_sdk/tools/chunkers/__init__.py +3 -1
  188. alita_sdk/tools/chunkers/code/codeparser.py +1 -1
  189. alita_sdk/tools/chunkers/sematic/json_chunker.py +2 -1
  190. alita_sdk/tools/chunkers/sematic/markdown_chunker.py +97 -6
  191. alita_sdk/tools/chunkers/sematic/proposal_chunker.py +1 -1
  192. alita_sdk/tools/chunkers/universal_chunker.py +270 -0
  193. alita_sdk/tools/cloud/aws/__init__.py +12 -7
  194. alita_sdk/tools/cloud/azure/__init__.py +12 -7
  195. alita_sdk/tools/cloud/gcp/__init__.py +12 -7
  196. alita_sdk/tools/cloud/k8s/__init__.py +12 -7
  197. alita_sdk/tools/code/linter/__init__.py +10 -8
  198. alita_sdk/tools/code/loaders/codesearcher.py +3 -2
  199. alita_sdk/tools/code/sonar/__init__.py +21 -13
  200. alita_sdk/tools/code_indexer_toolkit.py +199 -0
  201. alita_sdk/tools/confluence/__init__.py +22 -14
  202. alita_sdk/tools/confluence/api_wrapper.py +197 -58
  203. alita_sdk/tools/confluence/loader.py +14 -2
  204. alita_sdk/tools/custom_open_api/__init__.py +12 -5
  205. alita_sdk/tools/elastic/__init__.py +11 -8
  206. alita_sdk/tools/elitea_base.py +546 -64
  207. alita_sdk/tools/figma/__init__.py +60 -11
  208. alita_sdk/tools/figma/api_wrapper.py +1400 -167
  209. alita_sdk/tools/figma/figma_client.py +73 -0
  210. alita_sdk/tools/figma/toon_tools.py +2748 -0
  211. alita_sdk/tools/github/__init__.py +18 -17
  212. alita_sdk/tools/github/api_wrapper.py +9 -26
  213. alita_sdk/tools/github/github_client.py +81 -12
  214. alita_sdk/tools/github/schemas.py +2 -1
  215. alita_sdk/tools/github/tool.py +5 -1
  216. alita_sdk/tools/gitlab/__init__.py +19 -13
  217. alita_sdk/tools/gitlab/api_wrapper.py +256 -80
  218. alita_sdk/tools/gitlab_org/__init__.py +14 -10
  219. alita_sdk/tools/google/bigquery/__init__.py +14 -13
  220. alita_sdk/tools/google/bigquery/tool.py +5 -1
  221. alita_sdk/tools/google_places/__init__.py +21 -11
  222. alita_sdk/tools/jira/__init__.py +22 -11
  223. alita_sdk/tools/jira/api_wrapper.py +315 -168
  224. alita_sdk/tools/keycloak/__init__.py +11 -8
  225. alita_sdk/tools/localgit/__init__.py +9 -3
  226. alita_sdk/tools/localgit/local_git.py +62 -54
  227. alita_sdk/tools/localgit/tool.py +5 -1
  228. alita_sdk/tools/memory/__init__.py +38 -14
  229. alita_sdk/tools/non_code_indexer_toolkit.py +7 -2
  230. alita_sdk/tools/ocr/__init__.py +11 -8
  231. alita_sdk/tools/openapi/__init__.py +491 -106
  232. alita_sdk/tools/openapi/api_wrapper.py +1357 -0
  233. alita_sdk/tools/openapi/tool.py +20 -0
  234. alita_sdk/tools/pandas/__init__.py +20 -12
  235. alita_sdk/tools/pandas/api_wrapper.py +40 -45
  236. alita_sdk/tools/pandas/dataframe/generator/base.py +3 -1
  237. alita_sdk/tools/postman/__init__.py +11 -11
  238. alita_sdk/tools/postman/api_wrapper.py +19 -8
  239. alita_sdk/tools/postman/postman_analysis.py +8 -1
  240. alita_sdk/tools/pptx/__init__.py +11 -10
  241. alita_sdk/tools/qtest/__init__.py +22 -14
  242. alita_sdk/tools/qtest/api_wrapper.py +1784 -88
  243. alita_sdk/tools/rally/__init__.py +13 -10
  244. alita_sdk/tools/report_portal/__init__.py +23 -16
  245. alita_sdk/tools/salesforce/__init__.py +22 -16
  246. alita_sdk/tools/servicenow/__init__.py +21 -16
  247. alita_sdk/tools/servicenow/api_wrapper.py +1 -1
  248. alita_sdk/tools/sharepoint/__init__.py +17 -14
  249. alita_sdk/tools/sharepoint/api_wrapper.py +179 -39
  250. alita_sdk/tools/sharepoint/authorization_helper.py +191 -1
  251. alita_sdk/tools/sharepoint/utils.py +8 -2
  252. alita_sdk/tools/slack/__init__.py +13 -8
  253. alita_sdk/tools/sql/__init__.py +22 -19
  254. alita_sdk/tools/sql/api_wrapper.py +71 -23
  255. alita_sdk/tools/testio/__init__.py +21 -13
  256. alita_sdk/tools/testrail/__init__.py +13 -11
  257. alita_sdk/tools/testrail/api_wrapper.py +214 -46
  258. alita_sdk/tools/utils/__init__.py +28 -4
  259. alita_sdk/tools/utils/content_parser.py +241 -55
  260. alita_sdk/tools/utils/text_operations.py +254 -0
  261. alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +83 -27
  262. alita_sdk/tools/xray/__init__.py +18 -14
  263. alita_sdk/tools/xray/api_wrapper.py +58 -113
  264. alita_sdk/tools/yagmail/__init__.py +9 -3
  265. alita_sdk/tools/zephyr/__init__.py +12 -7
  266. alita_sdk/tools/zephyr_enterprise/__init__.py +16 -9
  267. alita_sdk/tools/zephyr_enterprise/api_wrapper.py +30 -15
  268. alita_sdk/tools/zephyr_essential/__init__.py +16 -10
  269. alita_sdk/tools/zephyr_essential/api_wrapper.py +297 -54
  270. alita_sdk/tools/zephyr_essential/client.py +6 -4
  271. alita_sdk/tools/zephyr_scale/__init__.py +13 -8
  272. alita_sdk/tools/zephyr_scale/api_wrapper.py +39 -31
  273. alita_sdk/tools/zephyr_squad/__init__.py +12 -7
  274. {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/METADATA +184 -37
  275. alita_sdk-0.3.584.dist-info/RECORD +452 -0
  276. alita_sdk-0.3.584.dist-info/entry_points.txt +2 -0
  277. alita_sdk/tools/bitbucket/tools.py +0 -304
  278. alita_sdk-0.3.257.dist-info/RECORD +0 -343
  279. {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/WHEEL +0 -0
  280. {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/licenses/LICENSE +0 -0
  281. {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,7 @@ class XrayConfiguration(BaseModel):
7
7
  model_config = ConfigDict(
8
8
  json_schema_extra={
9
9
  "metadata": {
10
- "label": "Xray",
10
+ "label": "Xray Cloud",
11
11
  "icon_url": "xray.svg",
12
12
  "sections": {
13
13
  "auth": {
@@ -30,3 +30,96 @@ class XrayConfiguration(BaseModel):
30
30
  base_url: str = Field(description="Xray URL")
31
31
  client_id: Optional[str] = Field(description="Client ID")
32
32
  client_secret: Optional[SecretStr] = Field(description="Client secret")
33
+
34
+ @staticmethod
35
+ def check_connection(settings: dict) -> str | None:
36
+ """
37
+ Check the connection to Xray Cloud.
38
+
39
+ Args:
40
+ settings: Dictionary containing Xray configuration
41
+ - base_url: Xray Cloud URL (required)
42
+ - client_id: OAuth2 Client ID (required)
43
+ - client_secret: OAuth2 Client Secret (required)
44
+
45
+ Returns:
46
+ None if connection successful, error message string if failed
47
+ """
48
+ import requests
49
+
50
+ # Validate base_url
51
+ base_url = settings.get("base_url", "").strip()
52
+ if not base_url:
53
+ return "Xray URL is required"
54
+
55
+ # Normalize URL - remove trailing slashes
56
+ base_url = base_url.rstrip("/")
57
+
58
+ # Basic URL validation
59
+ if not base_url.startswith(("http://", "https://")):
60
+ return "Xray URL must start with http:// or https://"
61
+
62
+ # Validate client_id
63
+ client_id = settings.get("client_id", "").strip() if settings.get("client_id") else ""
64
+ if not client_id:
65
+ return "Xray client ID is required"
66
+
67
+ # Validate client_secret
68
+ client_secret = settings.get("client_secret")
69
+ if not client_secret:
70
+ return "Xray client secret is required"
71
+
72
+ # Extract client_secret value if it's a SecretStr
73
+ client_secret_value = client_secret.get_secret_value() if hasattr(client_secret, 'get_secret_value') else client_secret
74
+
75
+ if not client_secret_value or not str(client_secret_value).strip():
76
+ return "Xray client secret cannot be empty"
77
+
78
+ # Test connection using /api/v2/authenticate endpoint
79
+ # This is the OAuth2 token generation endpoint for Xray Cloud
80
+ auth_url = f"{base_url}/api/v2/authenticate"
81
+
82
+ auth_payload = {
83
+ "client_id": client_id,
84
+ "client_secret": str(client_secret_value).strip()
85
+ }
86
+
87
+ try:
88
+ response = requests.post(
89
+ auth_url,
90
+ json=auth_payload,
91
+ headers={"Content-Type": "application/json"},
92
+ timeout=10
93
+ )
94
+
95
+ # Check response status
96
+ if response.status_code == 200:
97
+ # Successfully authenticated and got token
98
+ return None
99
+ elif response.status_code == 401:
100
+ return "Authentication failed: invalid client ID or secret"
101
+ elif response.status_code == 403:
102
+ return "Access forbidden: check client credentials"
103
+ elif response.status_code == 400:
104
+ # Bad request - could be invalid format
105
+ try:
106
+ error_data = response.json()
107
+ error_msg = error_data.get("error", "Bad request")
108
+ return f"Bad request: {error_msg}"
109
+ except:
110
+ return "Bad request: check client ID and secret format"
111
+ elif response.status_code == 404:
112
+ return "Xray API endpoint not found: verify the Xray URL"
113
+ else:
114
+ return f"Xray API returned status code {response.status_code}"
115
+
116
+ except requests.exceptions.SSLError as e:
117
+ return f"SSL certificate verification failed: {str(e)}"
118
+ except requests.exceptions.ConnectionError:
119
+ return f"Cannot connect to Xray at {base_url}: connection refused"
120
+ except requests.exceptions.Timeout:
121
+ return f"Connection to Xray at {base_url} timed out"
122
+ except requests.exceptions.RequestException as e:
123
+ return f"Error connecting to Xray: {str(e)}"
124
+ except Exception as e:
125
+ return f"Unexpected error: {str(e)}"
@@ -10,7 +10,7 @@ class ZephyrEnterpriseConfiguration(BaseModel):
10
10
  "label": "Zephyr Enterprise",
11
11
  "icon_url": "zephyr.svg",
12
12
  "section": "credentials",
13
- "type": "zephyr-enterprise",
13
+ "type": "zephyr_enterprise",
14
14
  "categories": ["test management"],
15
15
  "extra_categories": ["zephyr", "test automation", "test case management", "test planning"],
16
16
  }
@@ -18,3 +18,96 @@ class ZephyrEnterpriseConfiguration(BaseModel):
18
18
  )
19
19
  base_url: str = Field(description="Zephyr base URL")
20
20
  token: Optional[SecretStr] = Field(description="API token")
21
+
22
+ @staticmethod
23
+ def check_connection(settings: dict) -> str | None:
24
+ """
25
+ Check the connection to Zephyr Enterprise.
26
+
27
+ Args:
28
+ settings: Dictionary containing Zephyr Enterprise configuration
29
+ - base_url: Zephyr Enterprise instance URL (required)
30
+ - token: API token for authentication (optional, anonymous access possible)
31
+
32
+ Returns:
33
+ None if connection successful, error message string if failed
34
+ """
35
+ import requests
36
+
37
+ # Validate base_url
38
+ base_url = settings.get("base_url", "").strip()
39
+ if not base_url:
40
+ return "Zephyr Enterprise URL is required"
41
+
42
+ # Normalize URL - remove trailing slashes
43
+ base_url = base_url.rstrip("/")
44
+
45
+ # Basic URL validation
46
+ if not base_url.startswith(("http://", "https://")):
47
+ return "Zephyr Enterprise URL must start with http:// or https://"
48
+
49
+ # Get token (optional)
50
+ token = settings.get("token")
51
+
52
+ # Prepare headers
53
+ headers = {}
54
+ has_token = False
55
+ if token:
56
+ # Extract token value if it's a SecretStr
57
+ token_value = token.get_secret_value() if hasattr(token, 'get_secret_value') else token
58
+ if token_value and str(token_value).strip():
59
+ headers["Authorization"] = f"Bearer {str(token_value).strip()}"
60
+ has_token = True
61
+
62
+ # Use different endpoints based on whether authentication is provided
63
+ # Note: /healthcheck may allow anonymous access, so we use authenticated endpoints when token is provided
64
+ if has_token:
65
+ # Test with an endpoint that requires authentication: /flex/services/rest/latest/project
66
+ # This endpoint lists projects and requires proper authentication
67
+ test_url = f"{base_url}/flex/services/rest/latest/user/current"
68
+ else:
69
+ # Without token, test basic connectivity with healthcheck
70
+ test_url = f"{base_url}/flex/services/rest/latest/healthcheck"
71
+
72
+ try:
73
+ response = requests.get(
74
+ test_url,
75
+ headers=headers,
76
+ timeout=10
77
+ )
78
+
79
+ # Check response status
80
+ if response.status_code == 200:
81
+ # Successfully connected
82
+ return None
83
+ elif response.status_code == 401:
84
+ if has_token:
85
+ return "Authentication failed: invalid API token"
86
+ else:
87
+ return "Authentication required: provide API token"
88
+ elif response.status_code == 403:
89
+ return "Access forbidden: check token permissions"
90
+ elif response.status_code == 404:
91
+ # If user endpoint not found, try healthcheck as fallback
92
+ if has_token:
93
+ try:
94
+ fallback_url = f"{base_url}/flex/services/rest/latest/healthcheck"
95
+ fallback_response = requests.get(fallback_url, headers=headers, timeout=10)
96
+ if fallback_response.status_code == 200:
97
+ return None
98
+ except:
99
+ pass
100
+ return "Zephyr Enterprise API endpoint not found: verify the Zephyr URL"
101
+ else:
102
+ return f"Zephyr Enterprise API returned status code {response.status_code}"
103
+
104
+ except requests.exceptions.SSLError as e:
105
+ return f"SSL certificate verification failed: {str(e)}"
106
+ except requests.exceptions.ConnectionError:
107
+ return f"Cannot connect to Zephyr Enterprise at {base_url}: connection refused"
108
+ except requests.exceptions.Timeout:
109
+ return f"Connection to Zephyr Enterprise at {base_url} timed out"
110
+ except requests.exceptions.RequestException as e:
111
+ return f"Error connecting to Zephyr Enterprise: {str(e)}"
112
+ except Exception as e:
113
+ return f"Unexpected error: {str(e)}"
@@ -0,0 +1,95 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel, ConfigDict, Field, SecretStr
4
+
5
+
6
+ class ZephyrEssentialConfiguration(BaseModel):
7
+ model_config = ConfigDict(
8
+ json_schema_extra={
9
+ "metadata": {
10
+ "label": "Zephyr Essential",
11
+ "icon_url": "zephyr.svg",
12
+ "section": "credentials",
13
+ "type": "zephyr_essential",
14
+ "categories": ["test management"],
15
+ "extra_categories": ["zephyr", "test automation", "test case management", "test planning"],
16
+ }
17
+ }
18
+ )
19
+ base_url: Optional[str] = Field(description="Zephyr Essential API Base URL", default=None)
20
+ token: SecretStr = Field(description="Zephyr Essential API Token")
21
+
22
+ @staticmethod
23
+ def check_connection(settings: dict) -> str | None:
24
+ """
25
+ Check the connection to Zephyr Essential (Zephyr Scale).
26
+
27
+ Args:
28
+ settings: Dictionary containing Zephyr Essential configuration
29
+ - base_url: Zephyr Essential API Base URL (optional, defaults to Zephyr Scale Cloud API)
30
+ - token: Zephyr Essential API Token (required)
31
+
32
+ Returns:
33
+ None if connection successful, error message string if failed
34
+ """
35
+ import requests
36
+
37
+ # Get base_url or use default
38
+ base_url = settings.get("base_url")
39
+ if base_url:
40
+ base_url = base_url.strip().rstrip("/")
41
+ # Validate URL format if provided
42
+ if not base_url.startswith(("http://", "https://")):
43
+ return "Zephyr Essential URL must start with http:// or https://"
44
+ else:
45
+ # Default to Zephyr Scale Cloud API
46
+ base_url = "https://api.zephyrscale.smartbear.com/v2"
47
+
48
+ # Validate token
49
+ token = settings.get("token")
50
+ if not token:
51
+ return "Zephyr Essential API token is required"
52
+
53
+ # Extract token value if it's a SecretStr
54
+ token_value = token.get_secret_value() if hasattr(token, 'get_secret_value') else token
55
+
56
+ if not token_value or not str(token_value).strip():
57
+ return "Zephyr Essential API token cannot be empty"
58
+
59
+ # Test connection using /projects endpoint (requires authentication)
60
+ test_url = f"{base_url}/projects"
61
+
62
+ headers = {
63
+ "Authorization": f"Bearer {str(token_value).strip()}"
64
+ }
65
+
66
+ try:
67
+ response = requests.get(
68
+ test_url,
69
+ headers=headers,
70
+ timeout=10
71
+ )
72
+
73
+ # Check response status
74
+ if response.status_code == 200:
75
+ # Successfully connected and authenticated
76
+ return None
77
+ elif response.status_code == 401:
78
+ return "Authentication failed: invalid API token"
79
+ elif response.status_code == 403:
80
+ return "Access forbidden: token lacks required permissions"
81
+ elif response.status_code == 404:
82
+ return "Zephyr Essential API endpoint not found: verify the API URL"
83
+ else:
84
+ return f"Zephyr Essential API returned status code {response.status_code}"
85
+
86
+ except requests.exceptions.SSLError as e:
87
+ return f"SSL certificate verification failed: {str(e)}"
88
+ except requests.exceptions.ConnectionError:
89
+ return f"Cannot connect to Zephyr Essential at {base_url}: connection refused"
90
+ except requests.exceptions.Timeout:
91
+ return f"Connection to Zephyr Essential at {base_url} timed out"
92
+ except requests.exceptions.RequestException as e:
93
+ return f"Error connecting to Zephyr Essential: {str(e)}"
94
+ except Exception as e:
95
+ return f"Unexpected error: {str(e)}"
@@ -4,7 +4,7 @@ from json import dumps
4
4
  import chardet
5
5
  import logging
6
6
 
7
- from alita_sdk.tools.utils.content_parser import parse_file_content
7
+ from ...tools.utils.content_parser import parse_file_content
8
8
 
9
9
  logger = logging.getLogger(__name__)
10
10
 
@@ -38,11 +38,21 @@ class Artifact:
38
38
  if len(data) == 0:
39
39
  # empty file might be created
40
40
  return ""
41
- if isinstance(data, dict) and data['error']:
42
- return f"{data['error']}. {data['content'] if data['content'] else ''}"
41
+ if isinstance(data, dict) and data.get('error'):
42
+ return f"{data['error']}. {data.get('content', '')}"
43
43
  detected = chardet.detect(data)
44
44
  if detected['encoding'] is not None:
45
- return data.decode(detected['encoding'])
45
+ try:
46
+ return data.decode(detected['encoding'])
47
+ except Exception:
48
+ logger.error("Error while default encoding")
49
+ return parse_file_content(file_name=artifact_name,
50
+ file_content=data,
51
+ is_capture_image=is_capture_image,
52
+ page_number=page_number,
53
+ sheet_name=sheet_name,
54
+ excel_by_sheets=excel_by_sheets,
55
+ llm=llm)
46
56
  else:
47
57
  return parse_file_content(file_name=artifact_name,
48
58
  file_content=data,
@@ -77,4 +87,11 @@ class Artifact:
77
87
  if not bucket_name:
78
88
  bucket_name = self.bucket_name
79
89
  return self.create(artifact_name, new_data, bucket_name)
90
+
91
+ def get_content_bytes(self,
92
+ artifact_name: str,
93
+ bucket_name: str = None):
94
+ if not bucket_name:
95
+ bucket_name = self.bucket_name
96
+ return self.client.download_artifact(bucket_name, artifact_name)
80
97