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
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ from typing import Optional
2
3
 
3
4
  from langchain_core.tools import ToolException
4
5
  from langgraph.store.base import BaseStore
@@ -8,13 +9,22 @@ from alita_sdk.tools import get_tools as alita_tools
8
9
  from .application import ApplicationToolkit
9
10
  from .artifact import ArtifactToolkit
10
11
  from .datasource import DatasourcesToolkit
12
+ from .planning import PlanningToolkit
11
13
  from .prompt import PromptToolkit
12
14
  from .subgraph import SubgraphToolkit
13
15
  from .vectorstore import VectorStoreToolkit
16
+ from .mcp import McpToolkit
17
+ from .skill_router import SkillRouterToolkit
14
18
  from ..tools.mcp_server_tool import McpServerTool
19
+ from ..tools.sandbox import SandboxToolkit
20
+ from ..tools.image_generation import ImageGenerationToolkit
21
+ from ..tools.data_analysis import DataAnalysisToolkit
15
22
  # Import community tools
16
23
  from ...community import get_toolkits as community_toolkits, get_tools as community_tools
17
24
  from ...tools.memory import MemoryToolkit
25
+ from ..utils.mcp_oauth import canonical_resource, McpAuthorizationRequired
26
+ from ...tools.utils import clean_string
27
+ from alita_sdk.tools import _inject_toolkit_id
18
28
 
19
29
  logger = logging.getLogger(__name__)
20
30
 
@@ -23,78 +33,291 @@ def get_toolkits():
23
33
  core_toolkits = [
24
34
  ArtifactToolkit.toolkit_config_schema(),
25
35
  MemoryToolkit.toolkit_config_schema(),
26
- VectorStoreToolkit.toolkit_config_schema()
36
+ PlanningToolkit.toolkit_config_schema(),
37
+ VectorStoreToolkit.toolkit_config_schema(),
38
+ SandboxToolkit.toolkit_config_schema(),
39
+ ImageGenerationToolkit.toolkit_config_schema(),
40
+ DataAnalysisToolkit.toolkit_config_schema(),
41
+ McpToolkit.toolkit_config_schema(),
42
+ SkillRouterToolkit.toolkit_config_schema()
27
43
  ]
28
44
 
29
45
  return core_toolkits + community_toolkits() + alita_toolkits()
30
46
 
31
47
 
32
- def get_tools(tools_list: list, alita_client, llm, memory_store: BaseStore = None) -> list:
48
+ def get_tools(tools_list: list, alita_client=None, llm=None, memory_store: BaseStore = None, debug_mode: Optional[bool] = False, mcp_tokens: Optional[dict] = None, conversation_id: Optional[str] = None, ignored_mcp_servers: Optional[list] = None) -> list:
49
+ # Sanitize tools_list to handle corrupted tool configurations
50
+ sanitized_tools = []
51
+ for tool in tools_list:
52
+ if isinstance(tool, dict):
53
+ # Check for corrupted structure where 'type' and 'name' contain the full tool config
54
+ if 'type' in tool and isinstance(tool['type'], dict):
55
+ # This is a corrupted tool - use the inner dict instead
56
+ logger.warning(f"Detected corrupted tool configuration (type=dict), fixing: {tool}")
57
+ actual_tool = tool['type'] # or tool['name'], they should be the same
58
+ sanitized_tools.append(actual_tool)
59
+ elif 'name' in tool and isinstance(tool['name'], dict):
60
+ # Another corruption pattern where name contains the full config
61
+ logger.warning(f"Detected corrupted tool configuration (name=dict), fixing: {tool}")
62
+ actual_tool = tool['name']
63
+ sanitized_tools.append(actual_tool)
64
+ elif 'type' in tool and isinstance(tool['type'], str):
65
+ # Valid tool configuration
66
+ sanitized_tools.append(tool)
67
+ else:
68
+ # Skip invalid/corrupted tools that can't be fixed
69
+ logger.warning(f"Skipping invalid tool configuration: {tool}")
70
+ else:
71
+ logger.warning(f"Skipping non-dict tool: {tool}")
72
+ # Skip non-dict tools
73
+
33
74
  prompts = []
34
75
  tools = []
76
+ unhandled_tools = [] # Track tools not handled by main processing
77
+
78
+ for tool in sanitized_tools:
79
+ # Flag to track if this tool was processed by the main loop
80
+ # Used to prevent double processing by fallback systems
81
+ tool_handled = False
82
+ try:
83
+ if tool['type'] == 'datasource':
84
+ tool_handled = True
85
+ tools.extend(DatasourcesToolkit.get_toolkit(
86
+ alita_client,
87
+ datasource_ids=[int(tool['settings']['datasource_id'])],
88
+ selected_tools=tool['settings']['selected_tools'],
89
+ toolkit_name=tool.get('toolkit_name', '') or tool.get('name', '')
90
+ ).get_tools())
91
+ elif tool['type'] == 'application':
92
+ tool_handled = True
93
+ tools.extend(ApplicationToolkit.get_toolkit(
94
+ alita_client,
95
+ application_id=int(tool['settings']['application_id']),
96
+ application_version_id=int(tool['settings']['application_version_id']),
97
+ selected_tools=[],
98
+ ignored_mcp_servers=ignored_mcp_servers
99
+ ).get_tools())
100
+ # backward compatibility for pipeline application type as subgraph node
101
+ if tool.get('agent_type', '') == 'pipeline':
102
+ # static get_toolkit returns a list of CompiledStateGraph stubs
103
+ tools.extend(SubgraphToolkit.get_toolkit(
104
+ alita_client,
105
+ application_id=int(tool['settings']['application_id']),
106
+ application_version_id=int(tool['settings']['application_version_id']),
107
+ app_api_key=alita_client.auth_token,
108
+ selected_tools=[],
109
+ llm=llm
110
+ ))
111
+ elif tool['type'] == 'memory':
112
+ tool_handled = True
113
+ tools += MemoryToolkit.get_toolkit(
114
+ namespace=tool['settings'].get('namespace', str(tool['id'])),
115
+ pgvector_configuration=tool['settings'].get('pgvector_configuration', {}),
116
+ store=memory_store,
117
+ ).get_tools()
118
+ # TODO: update configuration of internal tools
119
+ elif tool['type'] == 'internal_tool':
120
+ tool_handled = True
121
+ if tool['name'] == 'pyodide':
122
+ tools += SandboxToolkit.get_toolkit(
123
+ stateful=False,
124
+ allow_net=True,
125
+ alita_client=alita_client,
126
+ ).get_tools()
127
+ elif tool['name'] == 'image_generation':
128
+ if alita_client and alita_client.model_image_generation:
129
+ tools += ImageGenerationToolkit.get_toolkit(
130
+ client=alita_client,
131
+ ).get_tools()
132
+ else:
133
+ logger.warning("Image generation internal tool requested "
134
+ "but no image generation model configured")
135
+ elif tool['name'] == 'planner':
136
+ tools += PlanningToolkit.get_toolkit(
137
+ pgvector_configuration=tool.get('settings', {}).get('pgvector_configuration'),
138
+ conversation_id=conversation_id,
139
+ ).get_tools()
140
+ elif tool['name'] == 'data_analysis':
141
+ # Data Analysis internal tool - uses conversation attachment bucket
142
+ settings = tool.get('settings', {})
143
+ bucket_name = settings.get('bucket_name')
144
+ if bucket_name:
145
+ tools += DataAnalysisToolkit.get_toolkit(
146
+ alita_client=alita_client,
147
+ llm=llm,
148
+ bucket_name=bucket_name,
149
+ toolkit_name="Data Analyst",
150
+ ).get_tools()
151
+ else:
152
+ logger.warning("Data Analysis internal tool requested "
153
+ "but no bucket_name provided in settings")
154
+ elif tool['type'] == 'artifact':
155
+ tool_handled = True
156
+ toolkit_tools = ArtifactToolkit.get_toolkit(
157
+ client=alita_client,
158
+ bucket=tool['settings']['bucket'],
159
+ toolkit_name=tool.get('toolkit_name', ''),
160
+ selected_tools=tool['settings'].get('selected_tools', []),
161
+ llm=llm,
162
+ # indexer settings
163
+ pgvector_configuration=tool['settings'].get('pgvector_configuration', {}),
164
+ embedding_model=tool['settings'].get('embedding_model'),
165
+ collection_name=f"{tool.get('toolkit_name')}",
166
+ collection_schema=str(tool['settings'].get('id', tool.get('id', ''))),
167
+ ).get_tools()
168
+ # Inject toolkit_id for artifact tools as well
169
+ # Pass settings as the tool config since that's where the id field is
170
+ _inject_toolkit_id(tool['settings'], toolkit_tools)
171
+ tools.extend(toolkit_tools)
172
+
173
+ elif tool['type'] == 'vectorstore':
174
+ tool_handled = True
175
+ tools.extend(VectorStoreToolkit.get_toolkit(
176
+ llm=llm,
177
+ toolkit_name=tool.get('toolkit_name', ''),
178
+ **tool['settings']).get_tools())
179
+ elif tool['type'] == 'planning':
180
+ tool_handled = True
181
+ # Planning toolkit for multi-step task tracking
182
+ settings = tool.get('settings', {})
183
+
184
+ # Check if local mode is enabled (uses filesystem storage, ignores pgvector)
185
+ use_local = settings.get('local', False)
186
+
187
+ if use_local:
188
+ # Local mode - use filesystem storage
189
+ logger.info("Planning toolkit using local filesystem storage (local=true)")
190
+ pgvector_config = {}
191
+ else:
192
+ # Check if explicit connection_string is provided in pgvector_configuration
193
+ explicit_pgvector_config = settings.get('pgvector_configuration', {})
194
+ explicit_connstr = explicit_pgvector_config.get('connection_string') if explicit_pgvector_config else None
195
+
196
+ if explicit_connstr:
197
+ # Use explicitly provided connection string (overrides project secrets)
198
+ logger.info("Using explicit connection_string for planning toolkit")
199
+ pgvector_config = explicit_pgvector_config
200
+ else:
201
+ # Try to fetch pgvector_project_connstr from project secrets
202
+ pgvector_connstr = None
203
+ if alita_client:
204
+ try:
205
+ pgvector_connstr = alita_client.unsecret('pgvector_project_connstr')
206
+ if pgvector_connstr:
207
+ logger.info("Using pgvector_project_connstr for planning toolkit")
208
+ except Exception as e:
209
+ logger.debug(f"pgvector_project_connstr not available: {e}")
210
+
211
+ pgvector_config = {'connection_string': pgvector_connstr} if pgvector_connstr else {}
212
+
213
+ tools.extend(PlanningToolkit.get_toolkit(
214
+ toolkit_name=tool.get('toolkit_name', ''),
215
+ selected_tools=settings.get('selected_tools', []),
216
+ pgvector_configuration=pgvector_config,
217
+ conversation_id=conversation_id or settings.get('conversation_id'),
218
+ ).get_tools())
219
+ elif tool['type'] == 'mcp':
220
+ tool_handled = True
221
+ # remote mcp tool initialization with token injection
222
+ settings = dict(tool['settings'])
223
+ url = settings.get('url')
224
+
225
+ # Check if this MCP server should be ignored (user chose to continue without auth)
226
+ if ignored_mcp_servers and url:
227
+ canonical_url = canonical_resource(url)
228
+ if canonical_url in ignored_mcp_servers or url in ignored_mcp_servers:
229
+ logger.info(f"[MCP Auth] Skipping ignored MCP server: {url}")
230
+ continue
231
+
232
+ headers = settings.get('headers')
233
+ token_data = None
234
+ session_id = None
235
+ if mcp_tokens and url:
236
+ canonical_url = canonical_resource(url)
237
+ logger.info(f"[MCP Auth] Looking for token for URL: {url}")
238
+ logger.info(f"[MCP Auth] Canonical URL: {canonical_url}")
239
+ logger.info(f"[MCP Auth] Available tokens: {list(mcp_tokens.keys())}")
240
+ token_data = mcp_tokens.get(canonical_url)
241
+ if token_data:
242
+ logger.info(f"[MCP Auth] Found token data for {canonical_url}")
243
+ # Handle both old format (string) and new format (dict with access_token and session_id)
244
+ if isinstance(token_data, dict):
245
+ access_token = token_data.get('access_token')
246
+ session_id = token_data.get('session_id')
247
+ logger.info(f"[MCP Auth] Token data: access_token={'present' if access_token else 'missing'}, session_id={session_id or 'none'}")
248
+ else:
249
+ # Backward compatibility: treat as plain token string
250
+ access_token = token_data
251
+ logger.info(f"[MCP Auth] Using legacy token format (string)")
252
+ else:
253
+ access_token = None
254
+ logger.warning(f"[MCP Auth] No token found for {canonical_url}")
255
+ else:
256
+ access_token = None
257
+
258
+ if access_token:
259
+ merged_headers = dict(headers) if headers else {}
260
+ merged_headers.setdefault('Authorization', f'Bearer {access_token}')
261
+ settings['headers'] = merged_headers
262
+ logger.info(f"[MCP Auth] Added Authorization header for {url}")
263
+
264
+ # Pass session_id to MCP toolkit if available
265
+ if session_id:
266
+ settings['session_id'] = session_id
267
+ logger.info(f"[MCP Auth] Passing session_id to toolkit: {session_id}")
268
+ tools.extend(McpToolkit.get_toolkit(
269
+ toolkit_name=tool.get('toolkit_name', ''),
270
+ client=alita_client,
271
+ **settings).get_tools())
272
+ elif tool['type'] == 'skill_router':
273
+ tool_handled = True
274
+ # Skills Registry Router Toolkit
275
+ logger.info(f"Processing skill_router toolkit: {tool}")
276
+ try:
277
+ settings = tool.get('settings', {})
278
+ toolkit_name = tool.get('toolkit_name', '')
279
+ selected_tools = settings.get('selected_tools', [])
280
+
281
+ toolkit_tools = SkillRouterToolkit.get_toolkit(
282
+ client=alita_client,
283
+ llm=llm,
284
+ toolkit_name=toolkit_name,
285
+ selected_tools=selected_tools,
286
+ **settings
287
+ ).get_tools()
288
+
289
+ tools.extend(toolkit_tools)
290
+ logger.info(f"✅ Successfully added {len(toolkit_tools)} tools from SkillRouterToolkit")
291
+ except Exception as e:
292
+ logger.error(f"❌ Failed to initialize SkillRouterToolkit: {e}")
293
+ raise
294
+ except McpAuthorizationRequired:
295
+ # Re-raise auth required exceptions directly
296
+ raise
297
+ except Exception as e:
298
+ logger.error(f"Error initializing toolkit for tool '{tool.get('name', 'unknown')}': {e}", exc_info=True)
299
+ if debug_mode:
300
+ logger.info("Skipping tool initialization error due to debug mode.")
301
+ continue
302
+ else:
303
+ raise ToolException(f"Error initializing toolkit for tool '{tool.get('name', 'unknown')}': {e}")
304
+
305
+ # Track unhandled tools (make a copy to avoid reference issues)
306
+ if not tool_handled:
307
+ # Ensure we only add valid tool configurations to unhandled_tools
308
+ if isinstance(tool, dict) and 'type' in tool and isinstance(tool['type'], str):
309
+ unhandled_tools.append(dict(tool))
35
310
 
36
- for tool in tools_list:
37
- if tool['type'] == 'datasource':
38
- tools.extend(DatasourcesToolkit.get_toolkit(
39
- alita_client,
40
- datasource_ids=[int(tool['settings']['datasource_id'])],
41
- selected_tools=tool['settings']['selected_tools'],
42
- toolkit_name=tool.get('toolkit_name', '') or tool.get('name', '')
43
- ).get_tools())
44
- elif tool['type'] == 'application' and tool.get('agent_type', '') != 'pipeline' :
45
- tools.extend(ApplicationToolkit.get_toolkit(
46
- alita_client,
47
- application_id=int(tool['settings']['application_id']),
48
- application_version_id=int(tool['settings']['application_version_id']),
49
- selected_tools=[]
50
- ).get_tools())
51
- elif tool['type'] == 'application' and tool.get('agent_type', '') == 'pipeline':
52
- # static get_toolkit returns a list of CompiledStateGraph stubs
53
- tools.extend(SubgraphToolkit.get_toolkit(
54
- alita_client,
55
- application_id=int(tool['settings']['application_id']),
56
- application_version_id=int(tool['settings']['application_version_id']),
57
- app_api_key=alita_client.auth_token,
58
- selected_tools=[],
59
- llm=llm
60
- ))
61
- elif tool['type'] == 'memory':
62
- if memory_store is None:
63
- raise ToolException(f"Memory store is not provided for memory tool: {tool.get('name', tool.get('toolkit_name', 'unknown'))}")
64
- tools += MemoryToolkit.get_toolkit(
65
- namespace=tool['settings'].get('namespace', str(tool['id'])),
66
- store=memory_store,
67
- toolkit_name=tool.get('toolkit_name', '')
68
- ).get_tools()
69
- elif tool['type'] == 'artifact':
70
- tools.extend(ArtifactToolkit.get_toolkit(
71
- client=alita_client,
72
- bucket=tool['settings']['bucket'],
73
- toolkit_name=tool.get('toolkit_name', ''),
74
- selected_tools=tool['settings'].get('selected_tools', []),
75
- llm=tool['settings'].get('llm'),
76
- # indexer settings
77
- connection_string=tool['settings'].get('connection_string', None),
78
- collection_name=tool.get('toolkit_name'),
79
- embedding_model=tool['settings'].get('embedding_model'),
80
- embedding_model_params=tool['settings'].get('embedding_model_params', None),
81
- vectorstore_type="PGVector"
82
- ).get_tools())
83
- elif tool['type'] == 'vectorstore':
84
- tools.extend(VectorStoreToolkit.get_toolkit(
85
- llm=llm,
86
- toolkit_name=tool.get('toolkit_name', ''),
87
- **tool['settings']).get_tools())
88
-
89
311
  if len(prompts) > 0:
90
312
  tools += PromptToolkit.get_toolkit(alita_client, prompts).get_tools()
91
-
92
- # Add community tools
93
- tools += community_tools(tools_list, alita_client, llm)
94
- # Add alita tools
95
- tools += alita_tools(tools_list, alita_client, llm, memory_store)
96
- # Add MCP tools
97
- tools += _mcp_tools(tools_list, alita_client)
313
+
314
+ # Add community tools (only for unhandled tools)
315
+ tools += community_tools(unhandled_tools, alita_client, llm)
316
+ # Add alita tools (only for unhandled tools)
317
+ tools += alita_tools(unhandled_tools, alita_client, llm, memory_store)
318
+ # Add MCP tools registered via alita-mcp CLI (static registry)
319
+ # Note: Tools with type='mcp' are already handled in main loop above
320
+ tools += _mcp_tools(unhandled_tools, alita_client)
98
321
 
99
322
  # Sanitize tool names to meet OpenAI's function naming requirements
100
323
  # tools = _sanitize_tool_names(tools)
@@ -148,17 +371,26 @@ def _sanitize_tool_names(tools: list) -> list:
148
371
 
149
372
 
150
373
  def _mcp_tools(tools_list, alita):
374
+ """
375
+ Handle MCP tools registered via alita-mcp CLI (static registry).
376
+ Skips tools with type='mcp' as those are handled by dynamic discovery.
377
+ """
151
378
  try:
152
379
  all_available_toolkits = alita.get_mcp_toolkits()
153
380
  toolkit_lookup = {tk["name"]: tk for tk in all_available_toolkits}
154
381
  tools = []
155
382
  #
156
383
  for selected_toolkit in tools_list:
157
- toolkit_name = selected_toolkit['type']
158
- toolkit_conf = toolkit_lookup.get(toolkit_name)
384
+ server_toolkit_name = selected_toolkit['type']
385
+
386
+ # Skip tools with type='mcp' - they're handled by dynamic discovery
387
+ if server_toolkit_name == 'mcp':
388
+ continue
389
+
390
+ toolkit_conf = toolkit_lookup.get(server_toolkit_name)
159
391
  #
160
392
  if not toolkit_conf:
161
- logger.debug(f"Toolkit '{toolkit_name}' not found in available MCP toolkits. Skipping...")
393
+ logger.debug(f"Toolkit '{server_toolkit_name}' not found in available MCP toolkits. Skipping...")
162
394
  continue
163
395
  #
164
396
  available_tools = toolkit_conf.get("tools", [])
@@ -166,7 +398,11 @@ def _mcp_tools(tools_list, alita):
166
398
  for available_tool in available_tools:
167
399
  tool_name = available_tool.get("name", "").lower()
168
400
  if not selected_tools or tool_name in selected_tools:
169
- if server_tool := _init_single_mcp_tool(toolkit_name, available_tool, alita, selected_toolkit['settings']):
401
+ if server_tool := _init_single_mcp_tool(server_toolkit_name,
402
+ # selected_toolkit["name"] is None for toolkit_test
403
+ selected_toolkit["toolkit_name"] if selected_toolkit.get("toolkit_name")
404
+ else server_toolkit_name,
405
+ available_tool, alita, selected_toolkit['settings']):
170
406
  tools.append(server_tool)
171
407
  return tools
172
408
  except Exception:
@@ -174,19 +410,27 @@ def _mcp_tools(tools_list, alita):
174
410
  return []
175
411
 
176
412
 
177
- def _init_single_mcp_tool(toolkit_name, available_tool, alita, toolkit_settings):
413
+ def _init_single_mcp_tool(server_toolkit_name, toolkit_name, available_tool, alita, toolkit_settings):
178
414
  try:
415
+ # Use clean tool name without prefix
179
416
  tool_name = available_tool["name"]
417
+ # Add toolkit context to description (max 1000 chars)
418
+ toolkit_context = f" [Toolkit: {clean_string(toolkit_name)}]" if toolkit_name else ''
419
+ base_description = f"MCP for a tool '{tool_name}': {available_tool.get('description', '')}"
420
+ description = base_description
421
+ if toolkit_context and len(base_description + toolkit_context) <= 1000:
422
+ description = base_description + toolkit_context
423
+
180
424
  return McpServerTool(
181
425
  name=tool_name,
182
- description=available_tool.get("description", ""),
426
+ description=description,
183
427
  args_schema=McpServerTool.create_pydantic_model_from_schema(
184
428
  available_tool.get("inputSchema", {})
185
429
  ),
186
430
  client=alita,
187
- server=toolkit_name,
431
+ server=server_toolkit_name,
188
432
  tool_timeout_sec=toolkit_settings.get("timeout", 90)
189
433
  )
190
434
  except Exception as e:
191
- logger.error(f"Failed to create McpServerTool for '{toolkit_name}.{tool_name}': {e}")
435
+ logger.error(f"Failed to create McpServerTool ('{server_toolkit_name}') for '{toolkit_name}.{tool_name}': {e}")
192
436
  return None
@@ -1,7 +1,7 @@
1
1
  from logging import getLogger
2
2
  from typing import Any, List, Literal, Optional
3
3
 
4
- from alita_sdk.tools.utils import clean_string, TOOLKIT_SPLITTER
4
+ from alita_sdk.tools.utils import clean_string
5
5
  from pydantic import BaseModel, create_model, Field, ConfigDict
6
6
  from langchain_core.tools import BaseToolkit, BaseTool
7
7
  from alita_sdk.tools.base.tool import BaseAction
@@ -31,7 +31,8 @@ class VectorStoreToolkit(BaseToolkit):
31
31
  toolkit_name: Optional[str] = None,
32
32
  selected_tools: list[str] = []):
33
33
  logger.info("Selected tools: %s", selected_tools)
34
- prefix = clean_string(toolkit_name) + TOOLKIT_SPLITTER if toolkit_name else ''
34
+ # Use clean toolkit name for context (max 1000 chars in description)
35
+ toolkit_context = f" [Toolkit: {clean_string(toolkit_name)}]" if toolkit_name else ''
35
36
  if selected_tools is None:
36
37
  selected_tools = []
37
38
  tools = []
@@ -46,11 +47,16 @@ class VectorStoreToolkit(BaseToolkit):
46
47
  # if selected_tools:
47
48
  # if tool["name"] not in selected_tools:
48
49
  # continue
50
+ # Add toolkit context to description with character limit
51
+ description = tool["description"]
52
+ if toolkit_context and len(description + toolkit_context) <= 1000:
53
+ description = description + toolkit_context
49
54
  tools.append(BaseAction(
50
55
  api_wrapper=vectorstore_wrapper,
51
- name=f'{prefix}{tool["name"]}',
52
- description=tool["description"],
53
- args_schema=tool["args_schema"]
56
+ name=tool["name"],
57
+ description=description,
58
+ args_schema=tool["args_schema"],
59
+ metadata={"toolkit_name": toolkit_name, "toolkit_type": "vectorstore"} if toolkit_name else {}
54
60
  ))
55
61
  return cls(tools=tools)
56
62
 
@@ -0,0 +1,24 @@
1
+ """
2
+ Runtime tools module for Alita SDK.
3
+ This module provides various tools that can be used within LangGraph agents.
4
+ """
5
+
6
+ from .sandbox import PyodideSandboxTool, StatefulPyodideSandboxTool, create_sandbox_tool
7
+ from .echo import EchoTool
8
+ from .image_generation import (
9
+ ImageGenerationTool,
10
+ create_image_generation_tool,
11
+ ImageGenerationToolkit
12
+ )
13
+ from .skill_router import SkillRouterWrapper
14
+
15
+ __all__ = [
16
+ "PyodideSandboxTool",
17
+ "StatefulPyodideSandboxTool",
18
+ "create_sandbox_tool",
19
+ "EchoTool",
20
+ "ImageGenerationTool",
21
+ "ImageGenerationToolkit",
22
+ "create_image_generation_tool",
23
+ "SkillRouterWrapper"
24
+ ]
@@ -1,9 +1,9 @@
1
1
  import json
2
2
 
3
3
  from ..utils.utils import clean_string
4
- from langchain_core.tools import BaseTool
5
- from langchain_core.messages import BaseMessage, AIMessage, ToolCall
6
- from typing import Any, Type, Optional, Union
4
+ from langchain_core.tools import BaseTool, ToolException
5
+ from langchain_core.messages import BaseMessage, AIMessage, HumanMessage
6
+ from typing import Any, Type, Optional
7
7
  from pydantic import create_model, field_validator, BaseModel
8
8
  from pydantic.fields import FieldInfo
9
9
  from ..langchain.mixedAgentRenderes import convert_message_to_json
@@ -31,7 +31,12 @@ def formulate_query(kwargs):
31
31
  chat_history = []
32
32
  for each in kwargs.get('chat_history')[:]:
33
33
  chat_history.append(AIMessage(each))
34
- result = {"input": kwargs.get('task'), "chat_history": chat_history}
34
+ user_task = kwargs.get('task')
35
+ if not user_task:
36
+ raise ToolException("Task is required to invoke the application. "
37
+ "Check the provided input (some errors may happen on previous steps).")
38
+ input_message = HumanMessage(content=user_task)
39
+ result = {"input": [input_message], "chat_history": chat_history}
35
40
  for key, value in kwargs.items():
36
41
  if key not in ("task", "chat_history"):
37
42
  result[key] = value
@@ -45,6 +50,8 @@ class Application(BaseTool):
45
50
  application: Any
46
51
  args_schema: Type[BaseModel] = applicationToolSchema
47
52
  return_type: str = "str"
53
+ client: Any
54
+ args_runnable: dict = {}
48
55
 
49
56
  @field_validator('name', mode='before')
50
57
  @classmethod
@@ -61,6 +68,11 @@ class Application(BaseTool):
61
68
  return self._run(*config, **all_kwargs)
62
69
 
63
70
  def _run(self, *args, **kwargs):
71
+ if self.client and self.args_runnable:
72
+ # Recreate new LanggraphAgentRunnable in order to reflect the current input_mapping (it can be dynamic for pipelines).
73
+ # Actually, for pipelines agent toolkits LanggraphAgentRunnable is created (for LLMNode) before pipeline's schema parsing.
74
+ application_variables = {k: {"name": k, "value": v} for k, v in kwargs.items()}
75
+ self.application = self.client.application(**self.args_runnable, application_variables=application_variables)
64
76
  response = self.application.invoke(formulate_query(kwargs))
65
77
  if self.return_type == "str":
66
78
  return response["output"]