alita-sdk 0.3.379__py3-none-any.whl → 0.3.627__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 +156 -0
  6. alita_sdk/cli/agent_loader.py +245 -0
  7. alita_sdk/cli/agent_ui.py +228 -0
  8. alita_sdk/cli/agents.py +3113 -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/testcases/__init__.py +94 -0
  23. alita_sdk/cli/testcases/data_generation.py +119 -0
  24. alita_sdk/cli/testcases/discovery.py +96 -0
  25. alita_sdk/cli/testcases/executor.py +84 -0
  26. alita_sdk/cli/testcases/logger.py +85 -0
  27. alita_sdk/cli/testcases/parser.py +172 -0
  28. alita_sdk/cli/testcases/prompts.py +91 -0
  29. alita_sdk/cli/testcases/reporting.py +125 -0
  30. alita_sdk/cli/testcases/setup.py +108 -0
  31. alita_sdk/cli/testcases/test_runner.py +282 -0
  32. alita_sdk/cli/testcases/utils.py +39 -0
  33. alita_sdk/cli/testcases/validation.py +90 -0
  34. alita_sdk/cli/testcases/workflow.py +196 -0
  35. alita_sdk/cli/toolkit.py +327 -0
  36. alita_sdk/cli/toolkit_loader.py +85 -0
  37. alita_sdk/cli/tools/__init__.py +43 -0
  38. alita_sdk/cli/tools/approval.py +224 -0
  39. alita_sdk/cli/tools/filesystem.py +1751 -0
  40. alita_sdk/cli/tools/planning.py +389 -0
  41. alita_sdk/cli/tools/terminal.py +414 -0
  42. alita_sdk/community/__init__.py +72 -12
  43. alita_sdk/community/inventory/__init__.py +236 -0
  44. alita_sdk/community/inventory/config.py +257 -0
  45. alita_sdk/community/inventory/enrichment.py +2137 -0
  46. alita_sdk/community/inventory/extractors.py +1469 -0
  47. alita_sdk/community/inventory/ingestion.py +3172 -0
  48. alita_sdk/community/inventory/knowledge_graph.py +1457 -0
  49. alita_sdk/community/inventory/parsers/__init__.py +218 -0
  50. alita_sdk/community/inventory/parsers/base.py +295 -0
  51. alita_sdk/community/inventory/parsers/csharp_parser.py +907 -0
  52. alita_sdk/community/inventory/parsers/go_parser.py +851 -0
  53. alita_sdk/community/inventory/parsers/html_parser.py +389 -0
  54. alita_sdk/community/inventory/parsers/java_parser.py +593 -0
  55. alita_sdk/community/inventory/parsers/javascript_parser.py +629 -0
  56. alita_sdk/community/inventory/parsers/kotlin_parser.py +768 -0
  57. alita_sdk/community/inventory/parsers/markdown_parser.py +362 -0
  58. alita_sdk/community/inventory/parsers/python_parser.py +604 -0
  59. alita_sdk/community/inventory/parsers/rust_parser.py +858 -0
  60. alita_sdk/community/inventory/parsers/swift_parser.py +832 -0
  61. alita_sdk/community/inventory/parsers/text_parser.py +322 -0
  62. alita_sdk/community/inventory/parsers/yaml_parser.py +370 -0
  63. alita_sdk/community/inventory/patterns/__init__.py +61 -0
  64. alita_sdk/community/inventory/patterns/ast_adapter.py +380 -0
  65. alita_sdk/community/inventory/patterns/loader.py +348 -0
  66. alita_sdk/community/inventory/patterns/registry.py +198 -0
  67. alita_sdk/community/inventory/presets.py +535 -0
  68. alita_sdk/community/inventory/retrieval.py +1403 -0
  69. alita_sdk/community/inventory/toolkit.py +173 -0
  70. alita_sdk/community/inventory/toolkit_utils.py +176 -0
  71. alita_sdk/community/inventory/visualize.py +1370 -0
  72. alita_sdk/configurations/__init__.py +1 -1
  73. alita_sdk/configurations/ado.py +141 -20
  74. alita_sdk/configurations/bitbucket.py +94 -2
  75. alita_sdk/configurations/confluence.py +130 -1
  76. alita_sdk/configurations/figma.py +76 -0
  77. alita_sdk/configurations/gitlab.py +91 -0
  78. alita_sdk/configurations/jira.py +103 -0
  79. alita_sdk/configurations/openapi.py +329 -0
  80. alita_sdk/configurations/qtest.py +72 -1
  81. alita_sdk/configurations/report_portal.py +96 -0
  82. alita_sdk/configurations/sharepoint.py +148 -0
  83. alita_sdk/configurations/testio.py +83 -0
  84. alita_sdk/configurations/testrail.py +88 -0
  85. alita_sdk/configurations/xray.py +93 -0
  86. alita_sdk/configurations/zephyr_enterprise.py +93 -0
  87. alita_sdk/configurations/zephyr_essential.py +75 -0
  88. alita_sdk/runtime/clients/artifact.py +3 -3
  89. alita_sdk/runtime/clients/client.py +388 -46
  90. alita_sdk/runtime/clients/mcp_discovery.py +342 -0
  91. alita_sdk/runtime/clients/mcp_manager.py +262 -0
  92. alita_sdk/runtime/clients/sandbox_client.py +8 -21
  93. alita_sdk/runtime/langchain/_constants_bkup.py +1318 -0
  94. alita_sdk/runtime/langchain/assistant.py +157 -39
  95. alita_sdk/runtime/langchain/constants.py +647 -1
  96. alita_sdk/runtime/langchain/document_loaders/AlitaDocxMammothLoader.py +315 -3
  97. alita_sdk/runtime/langchain/document_loaders/AlitaExcelLoader.py +103 -60
  98. alita_sdk/runtime/langchain/document_loaders/AlitaJSONLinesLoader.py +77 -0
  99. alita_sdk/runtime/langchain/document_loaders/AlitaJSONLoader.py +10 -4
  100. alita_sdk/runtime/langchain/document_loaders/AlitaPowerPointLoader.py +226 -7
  101. alita_sdk/runtime/langchain/document_loaders/AlitaTextLoader.py +5 -2
  102. alita_sdk/runtime/langchain/document_loaders/constants.py +40 -19
  103. alita_sdk/runtime/langchain/langraph_agent.py +405 -84
  104. alita_sdk/runtime/langchain/utils.py +106 -7
  105. alita_sdk/runtime/llms/preloaded.py +2 -6
  106. alita_sdk/runtime/models/mcp_models.py +61 -0
  107. alita_sdk/runtime/skills/__init__.py +91 -0
  108. alita_sdk/runtime/skills/callbacks.py +498 -0
  109. alita_sdk/runtime/skills/discovery.py +540 -0
  110. alita_sdk/runtime/skills/executor.py +610 -0
  111. alita_sdk/runtime/skills/input_builder.py +371 -0
  112. alita_sdk/runtime/skills/models.py +330 -0
  113. alita_sdk/runtime/skills/registry.py +355 -0
  114. alita_sdk/runtime/skills/skill_runner.py +330 -0
  115. alita_sdk/runtime/toolkits/__init__.py +31 -0
  116. alita_sdk/runtime/toolkits/application.py +29 -10
  117. alita_sdk/runtime/toolkits/artifact.py +20 -11
  118. alita_sdk/runtime/toolkits/datasource.py +13 -6
  119. alita_sdk/runtime/toolkits/mcp.py +783 -0
  120. alita_sdk/runtime/toolkits/mcp_config.py +1048 -0
  121. alita_sdk/runtime/toolkits/planning.py +178 -0
  122. alita_sdk/runtime/toolkits/skill_router.py +238 -0
  123. alita_sdk/runtime/toolkits/subgraph.py +251 -6
  124. alita_sdk/runtime/toolkits/tools.py +356 -69
  125. alita_sdk/runtime/toolkits/vectorstore.py +11 -5
  126. alita_sdk/runtime/tools/__init__.py +10 -3
  127. alita_sdk/runtime/tools/application.py +27 -6
  128. alita_sdk/runtime/tools/artifact.py +511 -28
  129. alita_sdk/runtime/tools/data_analysis.py +183 -0
  130. alita_sdk/runtime/tools/function.py +67 -35
  131. alita_sdk/runtime/tools/graph.py +10 -4
  132. alita_sdk/runtime/tools/image_generation.py +148 -46
  133. alita_sdk/runtime/tools/llm.py +1003 -128
  134. alita_sdk/runtime/tools/loop.py +3 -1
  135. alita_sdk/runtime/tools/loop_output.py +3 -1
  136. alita_sdk/runtime/tools/mcp_inspect_tool.py +284 -0
  137. alita_sdk/runtime/tools/mcp_remote_tool.py +181 -0
  138. alita_sdk/runtime/tools/mcp_server_tool.py +8 -5
  139. alita_sdk/runtime/tools/planning/__init__.py +36 -0
  140. alita_sdk/runtime/tools/planning/models.py +246 -0
  141. alita_sdk/runtime/tools/planning/wrapper.py +607 -0
  142. alita_sdk/runtime/tools/router.py +2 -4
  143. alita_sdk/runtime/tools/sandbox.py +65 -48
  144. alita_sdk/runtime/tools/skill_router.py +776 -0
  145. alita_sdk/runtime/tools/tool.py +3 -1
  146. alita_sdk/runtime/tools/vectorstore.py +9 -3
  147. alita_sdk/runtime/tools/vectorstore_base.py +70 -14
  148. alita_sdk/runtime/utils/AlitaCallback.py +137 -21
  149. alita_sdk/runtime/utils/constants.py +5 -1
  150. alita_sdk/runtime/utils/mcp_client.py +492 -0
  151. alita_sdk/runtime/utils/mcp_oauth.py +361 -0
  152. alita_sdk/runtime/utils/mcp_sse_client.py +434 -0
  153. alita_sdk/runtime/utils/mcp_tools_discovery.py +124 -0
  154. alita_sdk/runtime/utils/serialization.py +155 -0
  155. alita_sdk/runtime/utils/streamlit.py +40 -13
  156. alita_sdk/runtime/utils/toolkit_utils.py +30 -9
  157. alita_sdk/runtime/utils/utils.py +36 -0
  158. alita_sdk/tools/__init__.py +134 -35
  159. alita_sdk/tools/ado/repos/__init__.py +51 -32
  160. alita_sdk/tools/ado/repos/repos_wrapper.py +148 -89
  161. alita_sdk/tools/ado/test_plan/__init__.py +25 -9
  162. alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +23 -1
  163. alita_sdk/tools/ado/utils.py +1 -18
  164. alita_sdk/tools/ado/wiki/__init__.py +25 -12
  165. alita_sdk/tools/ado/wiki/ado_wrapper.py +291 -22
  166. alita_sdk/tools/ado/work_item/__init__.py +26 -13
  167. alita_sdk/tools/ado/work_item/ado_wrapper.py +73 -11
  168. alita_sdk/tools/advanced_jira_mining/__init__.py +11 -8
  169. alita_sdk/tools/aws/delta_lake/__init__.py +13 -9
  170. alita_sdk/tools/aws/delta_lake/tool.py +5 -1
  171. alita_sdk/tools/azure_ai/search/__init__.py +11 -8
  172. alita_sdk/tools/azure_ai/search/api_wrapper.py +1 -1
  173. alita_sdk/tools/base/tool.py +5 -1
  174. alita_sdk/tools/base_indexer_toolkit.py +271 -84
  175. alita_sdk/tools/bitbucket/__init__.py +17 -11
  176. alita_sdk/tools/bitbucket/api_wrapper.py +59 -11
  177. alita_sdk/tools/bitbucket/cloud_api_wrapper.py +49 -35
  178. alita_sdk/tools/browser/__init__.py +5 -4
  179. alita_sdk/tools/carrier/__init__.py +5 -6
  180. alita_sdk/tools/carrier/backend_reports_tool.py +6 -6
  181. alita_sdk/tools/carrier/run_ui_test_tool.py +6 -6
  182. alita_sdk/tools/carrier/ui_reports_tool.py +5 -5
  183. alita_sdk/tools/chunkers/__init__.py +3 -1
  184. alita_sdk/tools/chunkers/code/treesitter/treesitter.py +37 -13
  185. alita_sdk/tools/chunkers/sematic/json_chunker.py +1 -0
  186. alita_sdk/tools/chunkers/sematic/markdown_chunker.py +97 -6
  187. alita_sdk/tools/chunkers/sematic/proposal_chunker.py +1 -1
  188. alita_sdk/tools/chunkers/universal_chunker.py +270 -0
  189. alita_sdk/tools/cloud/aws/__init__.py +10 -7
  190. alita_sdk/tools/cloud/azure/__init__.py +10 -7
  191. alita_sdk/tools/cloud/gcp/__init__.py +10 -7
  192. alita_sdk/tools/cloud/k8s/__init__.py +10 -7
  193. alita_sdk/tools/code/linter/__init__.py +10 -8
  194. alita_sdk/tools/code/loaders/codesearcher.py +3 -2
  195. alita_sdk/tools/code/sonar/__init__.py +11 -8
  196. alita_sdk/tools/code_indexer_toolkit.py +82 -22
  197. alita_sdk/tools/confluence/__init__.py +22 -16
  198. alita_sdk/tools/confluence/api_wrapper.py +107 -30
  199. alita_sdk/tools/confluence/loader.py +14 -2
  200. alita_sdk/tools/custom_open_api/__init__.py +12 -5
  201. alita_sdk/tools/elastic/__init__.py +11 -8
  202. alita_sdk/tools/elitea_base.py +493 -30
  203. alita_sdk/tools/figma/__init__.py +58 -11
  204. alita_sdk/tools/figma/api_wrapper.py +1235 -143
  205. alita_sdk/tools/figma/figma_client.py +73 -0
  206. alita_sdk/tools/figma/toon_tools.py +2748 -0
  207. alita_sdk/tools/github/__init__.py +14 -15
  208. alita_sdk/tools/github/github_client.py +224 -100
  209. alita_sdk/tools/github/graphql_client_wrapper.py +119 -33
  210. alita_sdk/tools/github/schemas.py +14 -5
  211. alita_sdk/tools/github/tool.py +5 -1
  212. alita_sdk/tools/github/tool_prompts.py +9 -22
  213. alita_sdk/tools/gitlab/__init__.py +16 -11
  214. alita_sdk/tools/gitlab/api_wrapper.py +218 -48
  215. alita_sdk/tools/gitlab_org/__init__.py +10 -9
  216. alita_sdk/tools/gitlab_org/api_wrapper.py +63 -64
  217. alita_sdk/tools/google/bigquery/__init__.py +13 -12
  218. alita_sdk/tools/google/bigquery/tool.py +5 -1
  219. alita_sdk/tools/google_places/__init__.py +11 -8
  220. alita_sdk/tools/google_places/api_wrapper.py +1 -1
  221. alita_sdk/tools/jira/__init__.py +17 -10
  222. alita_sdk/tools/jira/api_wrapper.py +92 -41
  223. alita_sdk/tools/keycloak/__init__.py +11 -8
  224. alita_sdk/tools/localgit/__init__.py +9 -3
  225. alita_sdk/tools/localgit/local_git.py +62 -54
  226. alita_sdk/tools/localgit/tool.py +5 -1
  227. alita_sdk/tools/memory/__init__.py +12 -4
  228. alita_sdk/tools/non_code_indexer_toolkit.py +1 -0
  229. alita_sdk/tools/ocr/__init__.py +11 -8
  230. alita_sdk/tools/openapi/__init__.py +491 -106
  231. alita_sdk/tools/openapi/api_wrapper.py +1368 -0
  232. alita_sdk/tools/openapi/tool.py +20 -0
  233. alita_sdk/tools/pandas/__init__.py +20 -12
  234. alita_sdk/tools/pandas/api_wrapper.py +38 -25
  235. alita_sdk/tools/pandas/dataframe/generator/base.py +3 -1
  236. alita_sdk/tools/postman/__init__.py +10 -9
  237. alita_sdk/tools/pptx/__init__.py +11 -10
  238. alita_sdk/tools/pptx/pptx_wrapper.py +1 -1
  239. alita_sdk/tools/qtest/__init__.py +31 -11
  240. alita_sdk/tools/qtest/api_wrapper.py +2135 -86
  241. alita_sdk/tools/rally/__init__.py +10 -9
  242. alita_sdk/tools/rally/api_wrapper.py +1 -1
  243. alita_sdk/tools/report_portal/__init__.py +12 -8
  244. alita_sdk/tools/salesforce/__init__.py +10 -8
  245. alita_sdk/tools/servicenow/__init__.py +17 -15
  246. alita_sdk/tools/servicenow/api_wrapper.py +1 -1
  247. alita_sdk/tools/sharepoint/__init__.py +10 -7
  248. alita_sdk/tools/sharepoint/api_wrapper.py +129 -38
  249. alita_sdk/tools/sharepoint/authorization_helper.py +191 -1
  250. alita_sdk/tools/sharepoint/utils.py +8 -2
  251. alita_sdk/tools/slack/__init__.py +10 -7
  252. alita_sdk/tools/slack/api_wrapper.py +2 -2
  253. alita_sdk/tools/sql/__init__.py +12 -9
  254. alita_sdk/tools/testio/__init__.py +10 -7
  255. alita_sdk/tools/testrail/__init__.py +11 -10
  256. alita_sdk/tools/testrail/api_wrapper.py +1 -1
  257. alita_sdk/tools/utils/__init__.py +9 -4
  258. alita_sdk/tools/utils/content_parser.py +103 -18
  259. alita_sdk/tools/utils/text_operations.py +410 -0
  260. alita_sdk/tools/utils/tool_prompts.py +79 -0
  261. alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +30 -13
  262. alita_sdk/tools/xray/__init__.py +13 -9
  263. alita_sdk/tools/yagmail/__init__.py +9 -3
  264. alita_sdk/tools/zephyr/__init__.py +10 -7
  265. alita_sdk/tools/zephyr_enterprise/__init__.py +11 -7
  266. alita_sdk/tools/zephyr_essential/__init__.py +10 -7
  267. alita_sdk/tools/zephyr_essential/api_wrapper.py +30 -13
  268. alita_sdk/tools/zephyr_essential/client.py +2 -2
  269. alita_sdk/tools/zephyr_scale/__init__.py +11 -8
  270. alita_sdk/tools/zephyr_scale/api_wrapper.py +2 -2
  271. alita_sdk/tools/zephyr_squad/__init__.py +10 -7
  272. {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/METADATA +154 -8
  273. alita_sdk-0.3.627.dist-info/RECORD +468 -0
  274. alita_sdk-0.3.627.dist-info/entry_points.txt +2 -0
  275. alita_sdk-0.3.379.dist-info/RECORD +0 -360
  276. {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/WHEEL +0 -0
  277. {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/licenses/LICENSE +0 -0
  278. {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,6 @@
1
- from typing import List, Any
1
+ from typing import List, Any, Optional
2
+ import logging
3
+ import yaml
2
4
 
3
5
  from langchain_core.tools import BaseTool
4
6
  from langgraph.checkpoint.memory import MemorySaver
@@ -8,7 +10,238 @@ from ..langchain.langraph_agent import create_graph, SUBGRAPH_REGISTRY
8
10
  from ..tools.graph import GraphTool
9
11
  from ..utils.utils import clean_string
10
12
 
13
+ logger = logging.getLogger(__name__)
11
14
 
15
+
16
+ def _resolve_bypass_chain(target: str, bypass_mapping: dict, all_printer_related: set, max_depth: int = 100) -> str:
17
+ """
18
+ Recursively follow bypass mapping chain to find the first non-printer target.
19
+
20
+ Args:
21
+ target: Starting target node ID
22
+ bypass_mapping: Mapping of printer_id -> successor_id
23
+ all_printer_related: Set of all printer and reset node IDs
24
+ max_depth: Maximum chain depth to prevent infinite loops
25
+
26
+ Returns:
27
+ Final non-printer target node ID
28
+ """
29
+ visited = set()
30
+ depth = 0
31
+
32
+ while target in all_printer_related or target in bypass_mapping:
33
+ if depth >= max_depth:
34
+ logger.error(f"Maximum bypass chain depth ({max_depth}) exceeded for target '{target}'")
35
+ break
36
+
37
+ if target in visited:
38
+ logger.error(f"Circular reference detected in bypass chain starting from '{target}'")
39
+ break
40
+
41
+ visited.add(target)
42
+
43
+ if target in bypass_mapping:
44
+ target = bypass_mapping[target]
45
+ depth += 1
46
+ logger.debug(f"Following bypass chain: depth={depth}, target={target}")
47
+ else:
48
+ # Target is in all_printer_related but not in bypass mapping
49
+ logger.warning(f"Target '{target}' is a printer node without bypass mapping")
50
+ break
51
+
52
+ return target
53
+
54
+
55
+ def _filter_printer_nodes_from_yaml(yaml_schema: str) -> str:
56
+ """
57
+ Filter out PrinterNodes and their reset nodes from a YAML schema.
58
+
59
+ This function removes:
60
+ 1. Nodes with type='printer'
61
+ 2. Reset nodes (pattern: {node_id}_reset)
62
+ 3. Rewires transitions to bypass removed printer nodes
63
+ 4. Removes printer nodes from interrupt configurations
64
+
65
+ Args:
66
+ yaml_schema: Original YAML schema string
67
+
68
+ Returns:
69
+ Filtered YAML schema string without PrinterNodes
70
+ """
71
+ try:
72
+ schema_dict = yaml.safe_load(yaml_schema)
73
+
74
+ if not schema_dict or 'nodes' not in schema_dict:
75
+ return yaml_schema
76
+
77
+ nodes = schema_dict.get('nodes', [])
78
+
79
+ # Step 1: Identify printer nodes and build bypass mapping
80
+ printer_nodes = set()
81
+ printer_reset_nodes = set()
82
+ printer_bypass_mapping = {} # printer_node_id -> actual_successor_id
83
+
84
+ # First pass: Identify all printer nodes and reset nodes
85
+ for node in nodes:
86
+ node_id = node.get('id')
87
+ node_type = node.get('type')
88
+
89
+ if not node_id:
90
+ continue
91
+
92
+ # Identify reset nodes by naming pattern
93
+ if node_id.endswith('_reset'):
94
+ printer_reset_nodes.add(node_id)
95
+ continue
96
+
97
+ # Identify main printer nodes
98
+ if node_type == 'printer':
99
+ printer_nodes.add(node_id)
100
+
101
+ # Second pass: Build bypass mapping for printer nodes
102
+ for node in nodes:
103
+ node_id = node.get('id')
104
+ node_type = node.get('type')
105
+
106
+ if not node_id or node_type != 'printer':
107
+ continue
108
+
109
+ # Try standard pattern first: Printer -> Printer_reset -> NextNode
110
+ reset_node_id = f"{node_id}_reset"
111
+ reset_node = next((n for n in nodes if n.get('id') == reset_node_id), None)
112
+
113
+ if reset_node:
114
+ # Standard pattern with reset node
115
+ actual_successor = reset_node.get('transition')
116
+ if actual_successor:
117
+ printer_bypass_mapping[node_id] = actual_successor
118
+ logger.debug(f"Printer bypass mapping (standard): {node_id} -> {actual_successor}")
119
+ else:
120
+ # Direct transition pattern: Printer -> NextNode (no reset node)
121
+ # Get the direct transition from the printer node
122
+ direct_transition = node.get('transition')
123
+ if direct_transition:
124
+ printer_bypass_mapping[node_id] = direct_transition
125
+ logger.debug(f"Printer bypass mapping (direct): {node_id} -> {direct_transition}")
126
+
127
+ # Create the set of all printer-related nodes early so it can be used in rewiring
128
+ all_printer_related = printer_nodes | printer_reset_nodes
129
+
130
+ # Step 2: Filter out printer nodes and reset nodes
131
+ filtered_nodes = []
132
+ for node in nodes:
133
+ node_id = node.get('id')
134
+ node_type = node.get('type')
135
+
136
+ # Skip printer nodes
137
+ if node_type == 'printer':
138
+ logger.debug(f"Filtering out printer node: {node_id}")
139
+ continue
140
+
141
+ # Skip reset nodes
142
+ if node_id in printer_reset_nodes:
143
+ logger.debug(f"Filtering out printer reset node: {node_id}")
144
+ continue
145
+
146
+ # Step 3: Rewire transitions in remaining nodes to bypass printer nodes
147
+ # Use recursive resolution to handle chains of printers
148
+ if 'transition' in node:
149
+ transition = node['transition']
150
+ if transition in printer_bypass_mapping or transition in all_printer_related:
151
+ new_transition = _resolve_bypass_chain(transition, printer_bypass_mapping, all_printer_related)
152
+ if new_transition != transition:
153
+ node['transition'] = new_transition
154
+ logger.debug(f"Rewired transition in node '{node_id}': {transition} -> {new_transition}")
155
+
156
+ # Handle conditional outputs
157
+ if 'condition' in node:
158
+ condition = node['condition']
159
+ if 'conditional_outputs' in condition:
160
+ new_outputs = []
161
+ for output in condition['conditional_outputs']:
162
+ if output in printer_bypass_mapping or output in all_printer_related:
163
+ resolved_output = _resolve_bypass_chain(output, printer_bypass_mapping, all_printer_related)
164
+ new_outputs.append(resolved_output)
165
+ else:
166
+ new_outputs.append(output)
167
+ condition['conditional_outputs'] = new_outputs
168
+
169
+ if 'default_output' in condition:
170
+ default = condition['default_output']
171
+ if default in printer_bypass_mapping or default in all_printer_related:
172
+ condition['default_output'] = _resolve_bypass_chain(default, printer_bypass_mapping, all_printer_related)
173
+
174
+ # Handle decision nodes
175
+ if 'decision' in node:
176
+ decision = node['decision']
177
+ if 'nodes' in decision:
178
+ new_nodes = []
179
+ for decision_node in decision['nodes']:
180
+ if decision_node in printer_bypass_mapping or decision_node in all_printer_related:
181
+ resolved_node = _resolve_bypass_chain(decision_node, printer_bypass_mapping, all_printer_related)
182
+ new_nodes.append(resolved_node)
183
+ else:
184
+ new_nodes.append(decision_node)
185
+ decision['nodes'] = new_nodes
186
+
187
+ # Handle routes (for router nodes)
188
+ if 'routes' in node:
189
+ routes = node['routes']
190
+ if isinstance(routes, list):
191
+ new_routes = []
192
+ for route in routes:
193
+ if isinstance(route, dict) and 'target' in route:
194
+ target = route['target']
195
+ if target in printer_bypass_mapping or target in all_printer_related:
196
+ route['target'] = _resolve_bypass_chain(target, printer_bypass_mapping, all_printer_related)
197
+ new_routes.append(route)
198
+ node['routes'] = new_routes
199
+
200
+ filtered_nodes.append(node)
201
+
202
+ # Update the nodes in schema
203
+ schema_dict['nodes'] = filtered_nodes
204
+
205
+ # Step 4: Filter printer nodes from interrupt configurations
206
+ if 'interrupt_before' in schema_dict:
207
+ schema_dict['interrupt_before'] = [
208
+ i for i in schema_dict['interrupt_before']
209
+ if i not in all_printer_related
210
+ ]
211
+
212
+ if 'interrupt_after' in schema_dict:
213
+ schema_dict['interrupt_after'] = [
214
+ i for i in schema_dict['interrupt_after']
215
+ if i not in all_printer_related
216
+ ]
217
+
218
+ # Update entry point if it points to a printer node
219
+ # Use helper function to recursively resolve the chain
220
+ if 'entry_point' in schema_dict:
221
+ entry_point = schema_dict['entry_point']
222
+ original_entry = entry_point
223
+
224
+ # Check if entry point is a printer node (directly or in bypass mapping)
225
+ if entry_point in all_printer_related or entry_point in printer_bypass_mapping:
226
+ # Use helper function to resolve the chain
227
+ resolved_entry = _resolve_bypass_chain(entry_point, printer_bypass_mapping, all_printer_related)
228
+
229
+ if resolved_entry != original_entry:
230
+ schema_dict['entry_point'] = resolved_entry
231
+ logger.info(f"Updated entry point: {original_entry} -> {resolved_entry}")
232
+
233
+
234
+ # Convert back to YAML
235
+ filtered_yaml = yaml.dump(schema_dict, default_flow_style=False, sort_keys=False)
236
+ return filtered_yaml
237
+
238
+ except Exception as e:
239
+ logger.error(f"Error filtering PrinterNodes from YAML: {e}", exc_info=True)
240
+ # Return original YAML if filtering fails
241
+ return yaml_schema
242
+
243
+
244
+ # TODO: deprecate next release (1/15/2026)
12
245
  class SubgraphToolkit:
13
246
 
14
247
  @staticmethod
@@ -18,21 +251,33 @@ class SubgraphToolkit:
18
251
  application_version_id: int,
19
252
  llm,
20
253
  app_api_key: str,
21
- selected_tools: list[str] = []
254
+ selected_tools: list[str] = [],
255
+ is_subgraph: bool = True,
256
+ mcp_tokens: Optional[dict] = None,
257
+ ignored_mcp_servers: Optional[list] = None
22
258
  ) -> List[BaseTool]:
23
259
  from .tools import get_tools
24
260
  # from langgraph.checkpoint.memory import MemorySaver
25
261
 
26
262
  app_details = client.get_app_details(application_id)
27
263
  version_details = client.get_app_version_details(application_id, application_version_id)
28
- tools = get_tools(version_details['tools'], alita_client=client, llm=llm)
264
+ tools = get_tools(version_details['tools'], alita_client=client, llm=llm,
265
+ mcp_tokens=mcp_tokens, ignored_mcp_servers=ignored_mcp_servers)
29
266
 
30
267
  # Get the subgraph name
31
268
  subgraph_name = app_details.get("name")
32
269
 
270
+ # Get the original YAML
271
+ yaml_schema = version_details['instructions']
272
+
273
+ # Filter PrinterNodes from YAML if this is a subgraph
274
+ if is_subgraph:
275
+ yaml_schema = _filter_printer_nodes_from_yaml(yaml_schema)
276
+ logger.info(f"Filtered PrinterNodes from subgraph pipeline '{subgraph_name}'")
277
+
33
278
  # Populate the registry for flattening approach
34
279
  SUBGRAPH_REGISTRY[subgraph_name] = {
35
- 'yaml': version_details['instructions'],
280
+ 'yaml': yaml_schema, # Use filtered YAML
36
281
  'tools': tools,
37
282
  'flattened': False
38
283
  }
@@ -43,11 +288,11 @@ class SubgraphToolkit:
43
288
  graph = create_graph(
44
289
  client=llm,
45
290
  tools=tools,
46
- yaml_schema=version_details['instructions'],
291
+ yaml_schema=yaml_schema, # Use filtered YAML
47
292
  debug=False,
48
293
  store=None,
49
294
  memory=MemorySaver(),
50
- # for_subgraph=True, # compile as raw subgraph
295
+ for_subgraph=is_subgraph, # Pass flag to create_graph
51
296
  )
52
297
 
53
298
  cleaned_subgraph_name = clean_string(subgraph_name)