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.
- alita_sdk/cli/__init__.py +10 -0
- alita_sdk/cli/__main__.py +17 -0
- alita_sdk/cli/agent/__init__.py +5 -0
- alita_sdk/cli/agent/default.py +258 -0
- alita_sdk/cli/agent_executor.py +156 -0
- alita_sdk/cli/agent_loader.py +245 -0
- alita_sdk/cli/agent_ui.py +228 -0
- alita_sdk/cli/agents.py +3113 -0
- alita_sdk/cli/callbacks.py +647 -0
- alita_sdk/cli/cli.py +168 -0
- alita_sdk/cli/config.py +306 -0
- alita_sdk/cli/context/__init__.py +30 -0
- alita_sdk/cli/context/cleanup.py +198 -0
- alita_sdk/cli/context/manager.py +731 -0
- alita_sdk/cli/context/message.py +285 -0
- alita_sdk/cli/context/strategies.py +289 -0
- alita_sdk/cli/context/token_estimation.py +127 -0
- alita_sdk/cli/formatting.py +182 -0
- alita_sdk/cli/input_handler.py +419 -0
- alita_sdk/cli/inventory.py +1073 -0
- alita_sdk/cli/mcp_loader.py +315 -0
- alita_sdk/cli/testcases/__init__.py +94 -0
- alita_sdk/cli/testcases/data_generation.py +119 -0
- alita_sdk/cli/testcases/discovery.py +96 -0
- alita_sdk/cli/testcases/executor.py +84 -0
- alita_sdk/cli/testcases/logger.py +85 -0
- alita_sdk/cli/testcases/parser.py +172 -0
- alita_sdk/cli/testcases/prompts.py +91 -0
- alita_sdk/cli/testcases/reporting.py +125 -0
- alita_sdk/cli/testcases/setup.py +108 -0
- alita_sdk/cli/testcases/test_runner.py +282 -0
- alita_sdk/cli/testcases/utils.py +39 -0
- alita_sdk/cli/testcases/validation.py +90 -0
- alita_sdk/cli/testcases/workflow.py +196 -0
- alita_sdk/cli/toolkit.py +327 -0
- alita_sdk/cli/toolkit_loader.py +85 -0
- alita_sdk/cli/tools/__init__.py +43 -0
- alita_sdk/cli/tools/approval.py +224 -0
- alita_sdk/cli/tools/filesystem.py +1751 -0
- alita_sdk/cli/tools/planning.py +389 -0
- alita_sdk/cli/tools/terminal.py +414 -0
- alita_sdk/community/__init__.py +72 -12
- alita_sdk/community/inventory/__init__.py +236 -0
- alita_sdk/community/inventory/config.py +257 -0
- alita_sdk/community/inventory/enrichment.py +2137 -0
- alita_sdk/community/inventory/extractors.py +1469 -0
- alita_sdk/community/inventory/ingestion.py +3172 -0
- alita_sdk/community/inventory/knowledge_graph.py +1457 -0
- alita_sdk/community/inventory/parsers/__init__.py +218 -0
- alita_sdk/community/inventory/parsers/base.py +295 -0
- alita_sdk/community/inventory/parsers/csharp_parser.py +907 -0
- alita_sdk/community/inventory/parsers/go_parser.py +851 -0
- alita_sdk/community/inventory/parsers/html_parser.py +389 -0
- alita_sdk/community/inventory/parsers/java_parser.py +593 -0
- alita_sdk/community/inventory/parsers/javascript_parser.py +629 -0
- alita_sdk/community/inventory/parsers/kotlin_parser.py +768 -0
- alita_sdk/community/inventory/parsers/markdown_parser.py +362 -0
- alita_sdk/community/inventory/parsers/python_parser.py +604 -0
- alita_sdk/community/inventory/parsers/rust_parser.py +858 -0
- alita_sdk/community/inventory/parsers/swift_parser.py +832 -0
- alita_sdk/community/inventory/parsers/text_parser.py +322 -0
- alita_sdk/community/inventory/parsers/yaml_parser.py +370 -0
- alita_sdk/community/inventory/patterns/__init__.py +61 -0
- alita_sdk/community/inventory/patterns/ast_adapter.py +380 -0
- alita_sdk/community/inventory/patterns/loader.py +348 -0
- alita_sdk/community/inventory/patterns/registry.py +198 -0
- alita_sdk/community/inventory/presets.py +535 -0
- alita_sdk/community/inventory/retrieval.py +1403 -0
- alita_sdk/community/inventory/toolkit.py +173 -0
- alita_sdk/community/inventory/toolkit_utils.py +176 -0
- alita_sdk/community/inventory/visualize.py +1370 -0
- alita_sdk/configurations/__init__.py +1 -1
- alita_sdk/configurations/ado.py +141 -20
- alita_sdk/configurations/bitbucket.py +94 -2
- alita_sdk/configurations/confluence.py +130 -1
- alita_sdk/configurations/figma.py +76 -0
- alita_sdk/configurations/gitlab.py +91 -0
- alita_sdk/configurations/jira.py +103 -0
- alita_sdk/configurations/openapi.py +329 -0
- alita_sdk/configurations/qtest.py +72 -1
- alita_sdk/configurations/report_portal.py +96 -0
- alita_sdk/configurations/sharepoint.py +148 -0
- alita_sdk/configurations/testio.py +83 -0
- alita_sdk/configurations/testrail.py +88 -0
- alita_sdk/configurations/xray.py +93 -0
- alita_sdk/configurations/zephyr_enterprise.py +93 -0
- alita_sdk/configurations/zephyr_essential.py +75 -0
- alita_sdk/runtime/clients/artifact.py +3 -3
- alita_sdk/runtime/clients/client.py +388 -46
- alita_sdk/runtime/clients/mcp_discovery.py +342 -0
- alita_sdk/runtime/clients/mcp_manager.py +262 -0
- alita_sdk/runtime/clients/sandbox_client.py +8 -21
- alita_sdk/runtime/langchain/_constants_bkup.py +1318 -0
- alita_sdk/runtime/langchain/assistant.py +157 -39
- alita_sdk/runtime/langchain/constants.py +647 -1
- alita_sdk/runtime/langchain/document_loaders/AlitaDocxMammothLoader.py +315 -3
- alita_sdk/runtime/langchain/document_loaders/AlitaExcelLoader.py +103 -60
- alita_sdk/runtime/langchain/document_loaders/AlitaJSONLinesLoader.py +77 -0
- alita_sdk/runtime/langchain/document_loaders/AlitaJSONLoader.py +10 -4
- alita_sdk/runtime/langchain/document_loaders/AlitaPowerPointLoader.py +226 -7
- alita_sdk/runtime/langchain/document_loaders/AlitaTextLoader.py +5 -2
- alita_sdk/runtime/langchain/document_loaders/constants.py +40 -19
- alita_sdk/runtime/langchain/langraph_agent.py +405 -84
- alita_sdk/runtime/langchain/utils.py +106 -7
- alita_sdk/runtime/llms/preloaded.py +2 -6
- alita_sdk/runtime/models/mcp_models.py +61 -0
- alita_sdk/runtime/skills/__init__.py +91 -0
- alita_sdk/runtime/skills/callbacks.py +498 -0
- alita_sdk/runtime/skills/discovery.py +540 -0
- alita_sdk/runtime/skills/executor.py +610 -0
- alita_sdk/runtime/skills/input_builder.py +371 -0
- alita_sdk/runtime/skills/models.py +330 -0
- alita_sdk/runtime/skills/registry.py +355 -0
- alita_sdk/runtime/skills/skill_runner.py +330 -0
- alita_sdk/runtime/toolkits/__init__.py +31 -0
- alita_sdk/runtime/toolkits/application.py +29 -10
- alita_sdk/runtime/toolkits/artifact.py +20 -11
- alita_sdk/runtime/toolkits/datasource.py +13 -6
- alita_sdk/runtime/toolkits/mcp.py +783 -0
- alita_sdk/runtime/toolkits/mcp_config.py +1048 -0
- alita_sdk/runtime/toolkits/planning.py +178 -0
- alita_sdk/runtime/toolkits/skill_router.py +238 -0
- alita_sdk/runtime/toolkits/subgraph.py +251 -6
- alita_sdk/runtime/toolkits/tools.py +356 -69
- alita_sdk/runtime/toolkits/vectorstore.py +11 -5
- alita_sdk/runtime/tools/__init__.py +10 -3
- alita_sdk/runtime/tools/application.py +27 -6
- alita_sdk/runtime/tools/artifact.py +511 -28
- alita_sdk/runtime/tools/data_analysis.py +183 -0
- alita_sdk/runtime/tools/function.py +67 -35
- alita_sdk/runtime/tools/graph.py +10 -4
- alita_sdk/runtime/tools/image_generation.py +148 -46
- alita_sdk/runtime/tools/llm.py +1003 -128
- alita_sdk/runtime/tools/loop.py +3 -1
- alita_sdk/runtime/tools/loop_output.py +3 -1
- alita_sdk/runtime/tools/mcp_inspect_tool.py +284 -0
- alita_sdk/runtime/tools/mcp_remote_tool.py +181 -0
- alita_sdk/runtime/tools/mcp_server_tool.py +8 -5
- alita_sdk/runtime/tools/planning/__init__.py +36 -0
- alita_sdk/runtime/tools/planning/models.py +246 -0
- alita_sdk/runtime/tools/planning/wrapper.py +607 -0
- alita_sdk/runtime/tools/router.py +2 -4
- alita_sdk/runtime/tools/sandbox.py +65 -48
- alita_sdk/runtime/tools/skill_router.py +776 -0
- alita_sdk/runtime/tools/tool.py +3 -1
- alita_sdk/runtime/tools/vectorstore.py +9 -3
- alita_sdk/runtime/tools/vectorstore_base.py +70 -14
- alita_sdk/runtime/utils/AlitaCallback.py +137 -21
- alita_sdk/runtime/utils/constants.py +5 -1
- alita_sdk/runtime/utils/mcp_client.py +492 -0
- alita_sdk/runtime/utils/mcp_oauth.py +361 -0
- alita_sdk/runtime/utils/mcp_sse_client.py +434 -0
- alita_sdk/runtime/utils/mcp_tools_discovery.py +124 -0
- alita_sdk/runtime/utils/serialization.py +155 -0
- alita_sdk/runtime/utils/streamlit.py +40 -13
- alita_sdk/runtime/utils/toolkit_utils.py +30 -9
- alita_sdk/runtime/utils/utils.py +36 -0
- alita_sdk/tools/__init__.py +134 -35
- alita_sdk/tools/ado/repos/__init__.py +51 -32
- alita_sdk/tools/ado/repos/repos_wrapper.py +148 -89
- alita_sdk/tools/ado/test_plan/__init__.py +25 -9
- alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +23 -1
- alita_sdk/tools/ado/utils.py +1 -18
- alita_sdk/tools/ado/wiki/__init__.py +25 -12
- alita_sdk/tools/ado/wiki/ado_wrapper.py +291 -22
- alita_sdk/tools/ado/work_item/__init__.py +26 -13
- alita_sdk/tools/ado/work_item/ado_wrapper.py +73 -11
- alita_sdk/tools/advanced_jira_mining/__init__.py +11 -8
- alita_sdk/tools/aws/delta_lake/__init__.py +13 -9
- alita_sdk/tools/aws/delta_lake/tool.py +5 -1
- alita_sdk/tools/azure_ai/search/__init__.py +11 -8
- alita_sdk/tools/azure_ai/search/api_wrapper.py +1 -1
- alita_sdk/tools/base/tool.py +5 -1
- alita_sdk/tools/base_indexer_toolkit.py +271 -84
- alita_sdk/tools/bitbucket/__init__.py +17 -11
- alita_sdk/tools/bitbucket/api_wrapper.py +59 -11
- alita_sdk/tools/bitbucket/cloud_api_wrapper.py +49 -35
- alita_sdk/tools/browser/__init__.py +5 -4
- alita_sdk/tools/carrier/__init__.py +5 -6
- alita_sdk/tools/carrier/backend_reports_tool.py +6 -6
- alita_sdk/tools/carrier/run_ui_test_tool.py +6 -6
- alita_sdk/tools/carrier/ui_reports_tool.py +5 -5
- alita_sdk/tools/chunkers/__init__.py +3 -1
- alita_sdk/tools/chunkers/code/treesitter/treesitter.py +37 -13
- alita_sdk/tools/chunkers/sematic/json_chunker.py +1 -0
- alita_sdk/tools/chunkers/sematic/markdown_chunker.py +97 -6
- alita_sdk/tools/chunkers/sematic/proposal_chunker.py +1 -1
- alita_sdk/tools/chunkers/universal_chunker.py +270 -0
- alita_sdk/tools/cloud/aws/__init__.py +10 -7
- alita_sdk/tools/cloud/azure/__init__.py +10 -7
- alita_sdk/tools/cloud/gcp/__init__.py +10 -7
- alita_sdk/tools/cloud/k8s/__init__.py +10 -7
- alita_sdk/tools/code/linter/__init__.py +10 -8
- alita_sdk/tools/code/loaders/codesearcher.py +3 -2
- alita_sdk/tools/code/sonar/__init__.py +11 -8
- alita_sdk/tools/code_indexer_toolkit.py +82 -22
- alita_sdk/tools/confluence/__init__.py +22 -16
- alita_sdk/tools/confluence/api_wrapper.py +107 -30
- alita_sdk/tools/confluence/loader.py +14 -2
- alita_sdk/tools/custom_open_api/__init__.py +12 -5
- alita_sdk/tools/elastic/__init__.py +11 -8
- alita_sdk/tools/elitea_base.py +493 -30
- alita_sdk/tools/figma/__init__.py +58 -11
- alita_sdk/tools/figma/api_wrapper.py +1235 -143
- alita_sdk/tools/figma/figma_client.py +73 -0
- alita_sdk/tools/figma/toon_tools.py +2748 -0
- alita_sdk/tools/github/__init__.py +14 -15
- alita_sdk/tools/github/github_client.py +224 -100
- alita_sdk/tools/github/graphql_client_wrapper.py +119 -33
- alita_sdk/tools/github/schemas.py +14 -5
- alita_sdk/tools/github/tool.py +5 -1
- alita_sdk/tools/github/tool_prompts.py +9 -22
- alita_sdk/tools/gitlab/__init__.py +16 -11
- alita_sdk/tools/gitlab/api_wrapper.py +218 -48
- alita_sdk/tools/gitlab_org/__init__.py +10 -9
- alita_sdk/tools/gitlab_org/api_wrapper.py +63 -64
- alita_sdk/tools/google/bigquery/__init__.py +13 -12
- alita_sdk/tools/google/bigquery/tool.py +5 -1
- alita_sdk/tools/google_places/__init__.py +11 -8
- alita_sdk/tools/google_places/api_wrapper.py +1 -1
- alita_sdk/tools/jira/__init__.py +17 -10
- alita_sdk/tools/jira/api_wrapper.py +92 -41
- alita_sdk/tools/keycloak/__init__.py +11 -8
- alita_sdk/tools/localgit/__init__.py +9 -3
- alita_sdk/tools/localgit/local_git.py +62 -54
- alita_sdk/tools/localgit/tool.py +5 -1
- alita_sdk/tools/memory/__init__.py +12 -4
- alita_sdk/tools/non_code_indexer_toolkit.py +1 -0
- alita_sdk/tools/ocr/__init__.py +11 -8
- alita_sdk/tools/openapi/__init__.py +491 -106
- alita_sdk/tools/openapi/api_wrapper.py +1368 -0
- alita_sdk/tools/openapi/tool.py +20 -0
- alita_sdk/tools/pandas/__init__.py +20 -12
- alita_sdk/tools/pandas/api_wrapper.py +38 -25
- alita_sdk/tools/pandas/dataframe/generator/base.py +3 -1
- alita_sdk/tools/postman/__init__.py +10 -9
- alita_sdk/tools/pptx/__init__.py +11 -10
- alita_sdk/tools/pptx/pptx_wrapper.py +1 -1
- alita_sdk/tools/qtest/__init__.py +31 -11
- alita_sdk/tools/qtest/api_wrapper.py +2135 -86
- alita_sdk/tools/rally/__init__.py +10 -9
- alita_sdk/tools/rally/api_wrapper.py +1 -1
- alita_sdk/tools/report_portal/__init__.py +12 -8
- alita_sdk/tools/salesforce/__init__.py +10 -8
- alita_sdk/tools/servicenow/__init__.py +17 -15
- alita_sdk/tools/servicenow/api_wrapper.py +1 -1
- alita_sdk/tools/sharepoint/__init__.py +10 -7
- alita_sdk/tools/sharepoint/api_wrapper.py +129 -38
- alita_sdk/tools/sharepoint/authorization_helper.py +191 -1
- alita_sdk/tools/sharepoint/utils.py +8 -2
- alita_sdk/tools/slack/__init__.py +10 -7
- alita_sdk/tools/slack/api_wrapper.py +2 -2
- alita_sdk/tools/sql/__init__.py +12 -9
- alita_sdk/tools/testio/__init__.py +10 -7
- alita_sdk/tools/testrail/__init__.py +11 -10
- alita_sdk/tools/testrail/api_wrapper.py +1 -1
- alita_sdk/tools/utils/__init__.py +9 -4
- alita_sdk/tools/utils/content_parser.py +103 -18
- alita_sdk/tools/utils/text_operations.py +410 -0
- alita_sdk/tools/utils/tool_prompts.py +79 -0
- alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +30 -13
- alita_sdk/tools/xray/__init__.py +13 -9
- alita_sdk/tools/yagmail/__init__.py +9 -3
- alita_sdk/tools/zephyr/__init__.py +10 -7
- alita_sdk/tools/zephyr_enterprise/__init__.py +11 -7
- alita_sdk/tools/zephyr_essential/__init__.py +10 -7
- alita_sdk/tools/zephyr_essential/api_wrapper.py +30 -13
- alita_sdk/tools/zephyr_essential/client.py +2 -2
- alita_sdk/tools/zephyr_scale/__init__.py +11 -8
- alita_sdk/tools/zephyr_scale/api_wrapper.py +2 -2
- alita_sdk/tools/zephyr_squad/__init__.py +10 -7
- {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/METADATA +154 -8
- alita_sdk-0.3.627.dist-info/RECORD +468 -0
- alita_sdk-0.3.627.dist-info/entry_points.txt +2 -0
- alita_sdk-0.3.379.dist-info/RECORD +0 -360
- {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/licenses/LICENSE +0 -0
- {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':
|
|
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=
|
|
291
|
+
yaml_schema=yaml_schema, # Use filtered YAML
|
|
47
292
|
debug=False,
|
|
48
293
|
store=None,
|
|
49
294
|
memory=MemorySaver(),
|
|
50
|
-
|
|
295
|
+
for_subgraph=is_subgraph, # Pass flag to create_graph
|
|
51
296
|
)
|
|
52
297
|
|
|
53
298
|
cleaned_subgraph_name = clean_string(subgraph_name)
|