kailash 0.8.5__py3-none-any.whl → 0.8.7__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.
- kailash/__init__.py +5 -5
- kailash/channels/__init__.py +2 -1
- kailash/channels/mcp_channel.py +23 -4
- kailash/cli/validate_imports.py +202 -0
- kailash/core/resilience/bulkhead.py +15 -5
- kailash/core/resilience/circuit_breaker.py +4 -1
- kailash/core/resilience/health_monitor.py +312 -84
- kailash/edge/migration/edge_migration_service.py +384 -0
- kailash/mcp_server/protocol.py +26 -0
- kailash/mcp_server/server.py +1081 -8
- kailash/mcp_server/subscriptions.py +1560 -0
- kailash/mcp_server/transports.py +305 -0
- kailash/middleware/gateway/event_store.py +1 -0
- kailash/nodes/base.py +77 -1
- kailash/nodes/code/python.py +44 -3
- kailash/nodes/data/async_sql.py +42 -20
- kailash/nodes/edge/edge_migration_node.py +16 -12
- kailash/nodes/governance.py +410 -0
- kailash/nodes/rag/registry.py +1 -1
- kailash/nodes/transaction/distributed_transaction_manager.py +48 -1
- kailash/nodes/transaction/saga_state_storage.py +2 -1
- kailash/nodes/validation.py +8 -8
- kailash/runtime/local.py +30 -0
- kailash/runtime/validation/__init__.py +7 -15
- kailash/runtime/validation/import_validator.py +446 -0
- kailash/runtime/validation/suggestion_engine.py +5 -5
- kailash/utils/data_paths.py +74 -0
- kailash/workflow/builder.py +183 -4
- kailash/workflow/mermaid_visualizer.py +3 -1
- kailash/workflow/templates.py +6 -6
- kailash/workflow/validation.py +134 -3
- {kailash-0.8.5.dist-info → kailash-0.8.7.dist-info}/METADATA +20 -17
- {kailash-0.8.5.dist-info → kailash-0.8.7.dist-info}/RECORD +37 -31
- {kailash-0.8.5.dist-info → kailash-0.8.7.dist-info}/WHEEL +0 -0
- {kailash-0.8.5.dist-info → kailash-0.8.7.dist-info}/entry_points.txt +0 -0
- {kailash-0.8.5.dist-info → kailash-0.8.7.dist-info}/licenses/LICENSE +0 -0
- {kailash-0.8.5.dist-info → kailash-0.8.7.dist-info}/top_level.txt +0 -0
kailash/workflow/builder.py
CHANGED
@@ -4,10 +4,15 @@ import logging
|
|
4
4
|
import uuid
|
5
5
|
from typing import TYPE_CHECKING, Any, Optional, Union
|
6
6
|
|
7
|
-
from kailash.nodes.base import Node
|
7
|
+
from kailash.nodes.base import Node, NodeRegistry
|
8
8
|
from kailash.sdk_exceptions import ConnectionError, WorkflowValidationError
|
9
9
|
from kailash.workflow.contracts import ConnectionContract, get_contract_registry
|
10
10
|
from kailash.workflow.graph import Workflow
|
11
|
+
from kailash.workflow.validation import (
|
12
|
+
IssueSeverity,
|
13
|
+
ParameterDeclarationValidator,
|
14
|
+
ValidationIssue,
|
15
|
+
)
|
11
16
|
|
12
17
|
logger = logging.getLogger(__name__)
|
13
18
|
|
@@ -37,6 +42,160 @@ class WorkflowBuilder:
|
|
37
42
|
self.connection_contracts: dict[str, ConnectionContract] = {}
|
38
43
|
self._contract_registry = get_contract_registry()
|
39
44
|
|
45
|
+
# Parameter validation support
|
46
|
+
self._param_validator = ParameterDeclarationValidator()
|
47
|
+
|
48
|
+
def _is_sdk_node(self, node_class: type) -> bool:
|
49
|
+
"""Detect if node is SDK-provided vs custom implementation.
|
50
|
+
|
51
|
+
SDK nodes are registered in the NodeRegistry via @register_node decorator.
|
52
|
+
Custom nodes are not registered and require class reference usage.
|
53
|
+
|
54
|
+
Args:
|
55
|
+
node_class: The node class to check
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
True if node is registered in SDK (can use string reference),
|
59
|
+
False if custom node (must use class reference)
|
60
|
+
"""
|
61
|
+
if not hasattr(node_class, "__name__"):
|
62
|
+
return False
|
63
|
+
|
64
|
+
# Check if the node class is registered in the NodeRegistry
|
65
|
+
try:
|
66
|
+
registered_class = NodeRegistry.get(node_class.__name__)
|
67
|
+
# Check if it's the same class (identity check)
|
68
|
+
return registered_class is node_class
|
69
|
+
except Exception:
|
70
|
+
# Node not found in registry = custom node
|
71
|
+
return False
|
72
|
+
|
73
|
+
def _generate_intelligent_node_warning(self, node_class: type, node_id: str) -> str:
|
74
|
+
"""Generate context-aware warnings based on node type.
|
75
|
+
|
76
|
+
Args:
|
77
|
+
node_class: The node class being added
|
78
|
+
node_id: The node ID
|
79
|
+
|
80
|
+
Returns:
|
81
|
+
Appropriate warning message for the node type
|
82
|
+
"""
|
83
|
+
if self._is_sdk_node(node_class):
|
84
|
+
# SDK node using class reference - suggest string pattern
|
85
|
+
return (
|
86
|
+
f"SDK node detected. Consider using string reference for better compatibility:\n"
|
87
|
+
f" CURRENT: add_node({node_class.__name__}, '{node_id}', {{...}})\n"
|
88
|
+
f" PREFERRED: add_node('{node_class.__name__}', '{node_id}', {{...}})\n"
|
89
|
+
f"String references work for all @register_node() decorated SDK nodes."
|
90
|
+
)
|
91
|
+
else:
|
92
|
+
# Custom node using class reference - this is CORRECT
|
93
|
+
return (
|
94
|
+
f"✅ CUSTOM NODE USAGE CORRECT\n"
|
95
|
+
f"\n"
|
96
|
+
f"Pattern: add_node({node_class.__name__}, '{node_id}', {{...}})\n"
|
97
|
+
f"Status: This is the CORRECT pattern for custom nodes\n"
|
98
|
+
f"\n"
|
99
|
+
f'⚠️ IGNORE "preferred pattern" suggestions for custom nodes\n'
|
100
|
+
f"String references only work for @register_node() decorated SDK nodes.\n"
|
101
|
+
f"Custom nodes MUST use class references as shown above.\n"
|
102
|
+
f"\n"
|
103
|
+
f"📚 Guide: sdk-users/7-gold-standards/GOLD-STANDARD-custom-node-development-guide.md"
|
104
|
+
)
|
105
|
+
|
106
|
+
def validate_parameter_declarations(
|
107
|
+
self, warn_on_issues: bool = True
|
108
|
+
) -> list[ValidationIssue]:
|
109
|
+
"""Validate parameter declarations for all nodes in the workflow.
|
110
|
+
|
111
|
+
This method detects common parameter declaration issues that lead to
|
112
|
+
silent parameter dropping and debugging difficulties.
|
113
|
+
|
114
|
+
Args:
|
115
|
+
warn_on_issues: Whether to log warnings for detected issues
|
116
|
+
|
117
|
+
Returns:
|
118
|
+
List of ValidationIssue objects for any problems found
|
119
|
+
"""
|
120
|
+
all_issues = []
|
121
|
+
|
122
|
+
for node_id, node_info in self.nodes.items():
|
123
|
+
try:
|
124
|
+
# Create a temporary instance to validate parameter declarations
|
125
|
+
if "instance" in node_info:
|
126
|
+
# Use existing instance
|
127
|
+
node_instance = node_info["instance"]
|
128
|
+
workflow_params = {} # Instance already has config
|
129
|
+
elif "class" in node_info:
|
130
|
+
# Create temporary instance of custom node
|
131
|
+
node_class = node_info["class"]
|
132
|
+
node_config = node_info.get("config", {})
|
133
|
+
# Create minimal instance just for parameter validation
|
134
|
+
try:
|
135
|
+
node_instance = node_class(**node_config)
|
136
|
+
workflow_params = node_config
|
137
|
+
except Exception as e:
|
138
|
+
# If we can't create instance, skip detailed validation
|
139
|
+
all_issues.append(
|
140
|
+
ValidationIssue(
|
141
|
+
severity=IssueSeverity.WARNING,
|
142
|
+
category="parameter_declaration",
|
143
|
+
code="PAR005",
|
144
|
+
message=f"Could not validate parameters for custom node '{node_id}': {e}",
|
145
|
+
suggestion="Ensure node constructor accepts provided configuration parameters",
|
146
|
+
node_id=node_id,
|
147
|
+
)
|
148
|
+
)
|
149
|
+
continue
|
150
|
+
else:
|
151
|
+
# SDK node - validate if we can create it
|
152
|
+
node_type = node_info["type"]
|
153
|
+
node_config = node_info.get("config", {})
|
154
|
+
try:
|
155
|
+
# Try to get the class from registry
|
156
|
+
node_class = NodeRegistry.get(node_type)
|
157
|
+
node_instance = node_class(**node_config)
|
158
|
+
workflow_params = node_config
|
159
|
+
except Exception:
|
160
|
+
# Skip validation for nodes we can't instantiate
|
161
|
+
continue
|
162
|
+
|
163
|
+
# Validate parameter declarations
|
164
|
+
issues = self._param_validator.validate_node_parameters(
|
165
|
+
node_instance, workflow_params
|
166
|
+
)
|
167
|
+
|
168
|
+
# Add node_id to issues
|
169
|
+
for issue in issues:
|
170
|
+
issue.node_id = node_id
|
171
|
+
all_issues.append(issue)
|
172
|
+
|
173
|
+
# Log warnings if requested
|
174
|
+
if warn_on_issues:
|
175
|
+
if issue.severity == IssueSeverity.ERROR:
|
176
|
+
logger.error(
|
177
|
+
f"Parameter validation error in node '{node_id}': {issue.message}"
|
178
|
+
)
|
179
|
+
elif issue.severity == IssueSeverity.WARNING:
|
180
|
+
logger.warning(
|
181
|
+
f"Parameter validation warning in node '{node_id}': {issue.message}"
|
182
|
+
)
|
183
|
+
|
184
|
+
except Exception as e:
|
185
|
+
# General validation error
|
186
|
+
all_issues.append(
|
187
|
+
ValidationIssue(
|
188
|
+
severity=IssueSeverity.WARNING,
|
189
|
+
category="parameter_declaration",
|
190
|
+
code="PAR006",
|
191
|
+
message=f"Parameter validation failed for node '{node_id}': {e}",
|
192
|
+
suggestion="Check node configuration and parameter declarations",
|
193
|
+
node_id=node_id,
|
194
|
+
)
|
195
|
+
)
|
196
|
+
|
197
|
+
return all_issues
|
198
|
+
|
40
199
|
def add_node(self, *args, **kwargs) -> str:
|
41
200
|
"""
|
42
201
|
Unified add_node method supporting multiple API patterns.
|
@@ -105,6 +264,9 @@ class WorkflowBuilder:
|
|
105
264
|
# Two strings - assume current API: add_node("NodeType", "node_id")
|
106
265
|
config = kwargs if kwargs else (args[2] if len(args) > 2 else {})
|
107
266
|
return self._add_node_current(args[0], args[1], config)
|
267
|
+
elif isinstance(args[1], dict):
|
268
|
+
# Pattern: add_node("NodeType", {config}) - treat as add_node("NodeType", None, {config})
|
269
|
+
return self._add_node_current(args[0], None, args[1])
|
108
270
|
else:
|
109
271
|
# Invalid second argument
|
110
272
|
raise WorkflowValidationError(
|
@@ -202,10 +364,10 @@ class WorkflowBuilder:
|
|
202
364
|
if node_id is None:
|
203
365
|
node_id = f"node_{uuid.uuid4().hex[:8]}"
|
204
366
|
|
367
|
+
# Generate context-aware warning based on node type
|
368
|
+
warning_message = self._generate_intelligent_node_warning(node_class, node_id)
|
205
369
|
warnings.warn(
|
206
|
-
|
207
|
-
f" CURRENT: add_node({node_class.__name__}, '{node_id}', {list(config.keys())})\n"
|
208
|
-
f" PREFERRED: add_node('{node_class.__name__}', '{node_id}', {config})",
|
370
|
+
warning_message,
|
209
371
|
UserWarning,
|
210
372
|
stacklevel=3,
|
211
373
|
)
|
@@ -838,6 +1000,23 @@ class WorkflowBuilder:
|
|
838
1000
|
if self._edge_infrastructure:
|
839
1001
|
workflow.metadata["_edge_infrastructure"] = self._edge_infrastructure
|
840
1002
|
|
1003
|
+
# Validate parameter declarations before building workflow
|
1004
|
+
param_issues = self.validate_parameter_declarations(warn_on_issues=True)
|
1005
|
+
|
1006
|
+
# Check for critical parameter errors that should block workflow creation
|
1007
|
+
critical_errors = [
|
1008
|
+
issue for issue in param_issues if issue.severity == IssueSeverity.ERROR
|
1009
|
+
]
|
1010
|
+
if critical_errors:
|
1011
|
+
error_messages = [
|
1012
|
+
f"{issue.node_id}: {issue.message}" for issue in critical_errors
|
1013
|
+
]
|
1014
|
+
raise WorkflowValidationError(
|
1015
|
+
"Cannot build workflow due to parameter declaration errors:\n"
|
1016
|
+
+ "\n".join(f" - {msg}" for msg in error_messages)
|
1017
|
+
+ "\n\nSee: sdk-users/7-gold-standards/enterprise-parameter-passing-gold-standard.md"
|
1018
|
+
)
|
1019
|
+
|
841
1020
|
# Add nodes to workflow
|
842
1021
|
for node_id, node_info in self.nodes.items():
|
843
1022
|
try:
|
@@ -215,7 +215,9 @@ class MermaidVisualizer:
|
|
215
215
|
Sanitized node ID safe for Mermaid
|
216
216
|
"""
|
217
217
|
# Replace special characters with underscores
|
218
|
-
|
218
|
+
import re
|
219
|
+
|
220
|
+
sanitized = re.sub(r"[^a-zA-Z0-9_]", "_", node_id)
|
219
221
|
# Ensure it starts with a letter
|
220
222
|
if sanitized and sanitized[0].isdigit():
|
221
223
|
sanitized = f"node_{sanitized}"
|
kailash/workflow/templates.py
CHANGED
@@ -773,8 +773,8 @@ validation_result = {
|
|
773
773
|
|
774
774
|
# Add report generation node if not exists
|
775
775
|
if output not in workflow.nodes:
|
776
|
-
from kailash.examples.utils.data_paths import get_output_data_path
|
777
776
|
from kailash.nodes.data import JSONWriterNode
|
777
|
+
from kailash.utils.data_paths import get_output_data_path
|
778
778
|
|
779
779
|
workflow.add_node(
|
780
780
|
output,
|
@@ -814,8 +814,8 @@ validation_result = {
|
|
814
814
|
"""
|
815
815
|
# Add document reader if not exists
|
816
816
|
if document_reader not in workflow.nodes:
|
817
|
-
from kailash.examples.utils.data_paths import get_input_data_path
|
818
817
|
from kailash.nodes.data import DirectoryReaderNode
|
818
|
+
from kailash.utils.data_paths import get_input_data_path
|
819
819
|
|
820
820
|
workflow.add_node(
|
821
821
|
document_reader,
|
@@ -907,8 +907,8 @@ result = {
|
|
907
907
|
|
908
908
|
# Add output writer if not exists
|
909
909
|
if output not in workflow.nodes:
|
910
|
-
from kailash.examples.utils.data_paths import get_output_data_path
|
911
910
|
from kailash.nodes.data import JSONWriterNode
|
911
|
+
from kailash.utils.data_paths import get_output_data_path
|
912
912
|
|
913
913
|
workflow.add_node(
|
914
914
|
output,
|
@@ -1060,8 +1060,8 @@ validated_result = {
|
|
1060
1060
|
|
1061
1061
|
# Add output node if not exists
|
1062
1062
|
if output not in workflow.nodes:
|
1063
|
-
from kailash.examples.utils.data_paths import get_output_data_path
|
1064
1063
|
from kailash.nodes.data import JSONWriterNode
|
1064
|
+
from kailash.utils.data_paths import get_output_data_path
|
1065
1065
|
|
1066
1066
|
workflow.add_node(
|
1067
1067
|
output,
|
@@ -1106,8 +1106,8 @@ validated_result = {
|
|
1106
1106
|
"""
|
1107
1107
|
# Add data reader if not exists
|
1108
1108
|
if data_reader not in workflow.nodes:
|
1109
|
-
from kailash.examples.utils.data_paths import get_input_data_path
|
1110
1109
|
from kailash.nodes.data import CSVReaderNode
|
1110
|
+
from kailash.utils.data_paths import get_input_data_path
|
1111
1111
|
|
1112
1112
|
workflow.add_node(
|
1113
1113
|
data_reader,
|
@@ -1304,8 +1304,8 @@ result = {
|
|
1304
1304
|
|
1305
1305
|
# Add data writer if not exists
|
1306
1306
|
if writer not in workflow.nodes:
|
1307
|
-
from kailash.examples.utils.data_paths import get_output_data_path
|
1308
1307
|
from kailash.nodes.data import JSONWriterNode
|
1308
|
+
from kailash.utils.data_paths import get_output_data_path
|
1309
1309
|
|
1310
1310
|
workflow.add_node(
|
1311
1311
|
writer,
|
kailash/workflow/validation.py
CHANGED
@@ -116,9 +116,11 @@ See Also:
|
|
116
116
|
import re
|
117
117
|
from dataclasses import dataclass
|
118
118
|
from enum import Enum
|
119
|
-
from typing import Any
|
119
|
+
from typing import TYPE_CHECKING, Any
|
120
120
|
|
121
|
-
|
121
|
+
# Note: Workflow import moved to individual methods to avoid circular imports
|
122
|
+
if TYPE_CHECKING:
|
123
|
+
from kailash.workflow.graph import Workflow
|
122
124
|
|
123
125
|
|
124
126
|
class IssueSeverity(Enum):
|
@@ -143,6 +145,135 @@ class ValidationIssue:
|
|
143
145
|
documentation_link: str | None = None
|
144
146
|
|
145
147
|
|
148
|
+
class ParameterDeclarationValidator:
|
149
|
+
"""Validator for node parameter declarations - detects silent parameter dropping issues.
|
150
|
+
|
151
|
+
This validator addresses the critical issue where nodes with empty get_parameters()
|
152
|
+
methods silently receive no workflow parameters, leading to debugging issues.
|
153
|
+
|
154
|
+
Key validations:
|
155
|
+
1. Empty parameter declarations (PAR001 - WARNING at build time, enforced at runtime)
|
156
|
+
2. Undeclared parameter access attempts (PAR002 - WARNING)
|
157
|
+
3. Parameter type validation issues (PAR003 - WARNING)
|
158
|
+
4. Missing required parameters in workflow (PAR004 - WARNING at build time, ERROR at runtime)
|
159
|
+
|
160
|
+
Usage:
|
161
|
+
validator = ParameterDeclarationValidator()
|
162
|
+
issues = validator.validate_node_parameters(node_instance, workflow_params)
|
163
|
+
"""
|
164
|
+
|
165
|
+
validation_code = "PAR"
|
166
|
+
|
167
|
+
def validate_node_parameters(
|
168
|
+
self, node_instance, workflow_parameters: dict[str, Any]
|
169
|
+
) -> list[ValidationIssue]:
|
170
|
+
"""Check parameter declarations against workflow usage.
|
171
|
+
|
172
|
+
Args:
|
173
|
+
node_instance: Node instance to validate
|
174
|
+
workflow_parameters: Parameters provided by workflow
|
175
|
+
|
176
|
+
Returns:
|
177
|
+
List of ValidationIssue objects for any problems found
|
178
|
+
"""
|
179
|
+
issues = []
|
180
|
+
|
181
|
+
try:
|
182
|
+
declared_params = node_instance.get_parameters()
|
183
|
+
except Exception as e:
|
184
|
+
issues.append(
|
185
|
+
ValidationIssue(
|
186
|
+
severity=IssueSeverity.ERROR,
|
187
|
+
category="parameter_declaration",
|
188
|
+
code="PAR000",
|
189
|
+
message=f"Node {node_instance.__class__.__name__} get_parameters() failed: {e}",
|
190
|
+
suggestion="Fix get_parameters() method implementation",
|
191
|
+
documentation_link="sdk-users/7-gold-standards/enterprise-parameter-passing-gold-standard.md",
|
192
|
+
)
|
193
|
+
)
|
194
|
+
return issues
|
195
|
+
|
196
|
+
# Critical: Empty parameter declarations (addresses gold standard issue #2)
|
197
|
+
# For backwards compatibility, downgrade to WARNING at build time
|
198
|
+
if not declared_params and workflow_parameters:
|
199
|
+
workflow_param_names = list(workflow_parameters.keys())
|
200
|
+
issues.append(
|
201
|
+
ValidationIssue(
|
202
|
+
severity=IssueSeverity.WARNING,
|
203
|
+
category="parameter_declaration",
|
204
|
+
code="PAR001",
|
205
|
+
message=f"Node {node_instance.__class__.__name__} declares no parameters but workflow provides {workflow_param_names}",
|
206
|
+
suggestion="Add parameters to get_parameters() method - SDK only injects explicitly declared parameters",
|
207
|
+
documentation_link="sdk-users/7-gold-standards/enterprise-parameter-passing-gold-standard.md#parameter-declaration-security",
|
208
|
+
)
|
209
|
+
)
|
210
|
+
|
211
|
+
# Security: Undeclared parameter access attempts
|
212
|
+
if declared_params and workflow_parameters:
|
213
|
+
undeclared = set(workflow_parameters.keys()) - set(declared_params.keys())
|
214
|
+
if undeclared:
|
215
|
+
issues.append(
|
216
|
+
ValidationIssue(
|
217
|
+
severity=IssueSeverity.WARNING,
|
218
|
+
category="parameter_declaration",
|
219
|
+
code="PAR002",
|
220
|
+
message=f"Workflow parameters {list(undeclared)} not declared in get_parameters() - will be ignored by SDK",
|
221
|
+
suggestion="Add missing parameters to get_parameters() or remove from workflow configuration",
|
222
|
+
)
|
223
|
+
)
|
224
|
+
|
225
|
+
# Validation: Parameter type issues
|
226
|
+
if declared_params:
|
227
|
+
for param_name, param_def in declared_params.items():
|
228
|
+
if not hasattr(param_def, "type") or param_def.type is None:
|
229
|
+
issues.append(
|
230
|
+
ValidationIssue(
|
231
|
+
severity=IssueSeverity.WARNING,
|
232
|
+
category="parameter_declaration",
|
233
|
+
code="PAR003",
|
234
|
+
message=f"Parameter '{param_name}' missing type definition",
|
235
|
+
suggestion=f"Add type field to NodeParameter: NodeParameter(name='{param_name}', type=str, ...)",
|
236
|
+
)
|
237
|
+
)
|
238
|
+
|
239
|
+
# Check for required parameters without defaults
|
240
|
+
if (
|
241
|
+
getattr(param_def, "required", False)
|
242
|
+
and param_name not in workflow_parameters
|
243
|
+
):
|
244
|
+
if getattr(param_def, "default", None) is None:
|
245
|
+
# For backwards compatibility, missing required parameters are WARNING at build time
|
246
|
+
# They'll still cause runtime errors when the node executes
|
247
|
+
issues.append(
|
248
|
+
ValidationIssue(
|
249
|
+
severity=IssueSeverity.WARNING,
|
250
|
+
category="parameter_declaration",
|
251
|
+
code="PAR004",
|
252
|
+
message=f"Required parameter '{param_name}' not provided by workflow and has no default",
|
253
|
+
suggestion=f"Either provide '{param_name}' in workflow configuration or add default value",
|
254
|
+
)
|
255
|
+
)
|
256
|
+
|
257
|
+
return issues
|
258
|
+
|
259
|
+
def validate_workflow_node_parameters(self, workflow) -> list[ValidationIssue]:
|
260
|
+
"""Validate parameter declarations for all nodes in a workflow.
|
261
|
+
|
262
|
+
Args:
|
263
|
+
workflow: Workflow instance to validate
|
264
|
+
|
265
|
+
Returns:
|
266
|
+
List of all parameter declaration issues across the workflow
|
267
|
+
"""
|
268
|
+
all_issues = []
|
269
|
+
|
270
|
+
# This would need workflow.nodes to be iterable with node instances
|
271
|
+
# For now, we'll focus on the single-node validation method
|
272
|
+
# Implementation would depend on workflow structure
|
273
|
+
|
274
|
+
return all_issues
|
275
|
+
|
276
|
+
|
146
277
|
class CycleLinter:
|
147
278
|
"""
|
148
279
|
Comprehensive linter for cyclic workflows.
|
@@ -151,7 +282,7 @@ class CycleLinter:
|
|
151
282
|
and potential problems specific to cyclic execution.
|
152
283
|
"""
|
153
284
|
|
154
|
-
def __init__(self, workflow: Workflow):
|
285
|
+
def __init__(self, workflow: "Workflow"):
|
155
286
|
"""
|
156
287
|
Initialize linter with target workflow.
|
157
288
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: kailash
|
3
|
-
Version: 0.8.
|
3
|
+
Version: 0.8.7
|
4
4
|
Summary: Python SDK for the Kailash container-node architecture
|
5
5
|
Home-page: https://github.com/integrum/kailash-python-sdk
|
6
6
|
Author: Integrum
|
@@ -81,6 +81,7 @@ Requires-Dist: opentelemetry-instrumentation-fastapi>=0.55b1
|
|
81
81
|
Requires-Dist: seaborn>=0.13.2
|
82
82
|
Requires-Dist: sqlparse>=0.5.3
|
83
83
|
Requires-Dist: jsonschema>=4.24.0
|
84
|
+
Requires-Dist: openai>=1.97.1
|
84
85
|
Provides-Extra: dev
|
85
86
|
Requires-Dist: pytest>=7.0; extra == "dev"
|
86
87
|
Requires-Dist: pytest-cov>=3.0; extra == "dev"
|
@@ -116,18 +117,18 @@ Dynamic: requires-python
|
|
116
117
|
|
117
118
|
---
|
118
119
|
|
119
|
-
## 🔥 Latest Release: v0.8.
|
120
|
+
## 🔥 Latest Release: v0.8.5 (January 20, 2025)
|
120
121
|
|
121
|
-
**
|
122
|
+
**Architecture Cleanup & Enterprise Security**
|
122
123
|
|
123
|
-
-
|
124
|
-
-
|
125
|
-
-
|
126
|
-
-
|
127
|
-
-
|
128
|
-
- ✅ **
|
124
|
+
- 🏗️ **Architecture Clarity**: Removed confusing `src/kailash/nexus` module
|
125
|
+
- 🔒 **Connection Validation**: Enterprise-grade parameter validation with type safety
|
126
|
+
- 🌐 **Edge Computing**: 50+ new nodes for geo-distributed infrastructure
|
127
|
+
- 📊 **Advanced Monitoring**: AlertManager with proactive threshold monitoring
|
128
|
+
- 🚀 **Performance**: <1ms validation overhead with intelligent caching
|
129
|
+
- ✅ **Breaking Changes**: See [migration guide](sdk-users/6-reference/changelogs/releases/v0.8.5-2025-07-20.md)
|
129
130
|
|
130
|
-
[Full Changelog](
|
131
|
+
[Full Changelog](sdk-users/6-reference/changelogs/releases/v0.8.5-2025-07-20.md) | [PyPI Packages](https://pypi.org/project/kailash/0.8.5/)
|
131
132
|
|
132
133
|
## 🎯 What Makes Kailash Different
|
133
134
|
|
@@ -344,7 +345,7 @@ results, run_id = runtime.execute(workflow.build())
|
|
344
345
|
|
345
346
|
## 🚀 Applications Built with Kailash
|
346
347
|
|
347
|
-
### 1. DataFlow - Zero-Config Database Platform
|
348
|
+
### 1. DataFlow - Zero-Config Database Platform (v0.3.1)
|
348
349
|
```bash
|
349
350
|
pip install kailash-dataflow
|
350
351
|
```
|
@@ -352,8 +353,9 @@ pip install kailash-dataflow
|
|
352
353
|
- **Redis caching** with enterprise-grade invalidation
|
353
354
|
- **Automatic API generation** with OpenAPI documentation
|
354
355
|
- **4 production examples** with complete deployment guides
|
356
|
+
- **Latest**: v0.3.1 - Enhanced transaction support and schema management
|
355
357
|
|
356
|
-
### 2. Nexus - Multi-Channel Platform
|
358
|
+
### 2. Nexus - Multi-Channel Platform (v1.0.3)
|
357
359
|
```bash
|
358
360
|
pip install kailash-nexus
|
359
361
|
```
|
@@ -361,6 +363,7 @@ pip install kailash-nexus
|
|
361
363
|
- **Enterprise orchestration** with multi-tenancy
|
362
364
|
- **Session management** with cross-channel synchronization
|
363
365
|
- **105 tests** with comprehensive validation
|
366
|
+
- **Latest**: v1.0.3 - Production-ready release with enhanced stability
|
364
367
|
|
365
368
|
### 3. AI Registry - Advanced RAG Platform
|
366
369
|
```bash
|
@@ -421,8 +424,8 @@ pytest tests/e2e/ --timeout=10
|
|
421
424
|
|
422
425
|
### For Users
|
423
426
|
- **[SDK Users Guide](sdk-users/)**: Complete workflow development guide
|
424
|
-
- **[Node Selection Guide](sdk-users/nodes/node-selection-guide.md)**: Smart node selection with decision trees
|
425
|
-
- **[Enterprise Patterns](sdk-users/enterprise/)**: Production deployment patterns
|
427
|
+
- **[Node Selection Guide](sdk-users/2-core-concepts/nodes/node-selection-guide.md)**: Smart node selection with decision trees
|
428
|
+
- **[Enterprise Patterns](sdk-users/5-enterprise/)**: Production deployment patterns
|
426
429
|
- **[API Documentation](https://integrum.github.io/kailash-python-sdk)**: Complete API reference
|
427
430
|
|
428
431
|
### For Contributors
|
@@ -431,9 +434,9 @@ pytest tests/e2e/ --timeout=10
|
|
431
434
|
- **[Testing Guide](tests/README.md)**: 3-tier testing strategy
|
432
435
|
|
433
436
|
### Quick References
|
434
|
-
- **[Cheatsheet](sdk-users/cheatsheet/)**: 53 copy-paste patterns
|
435
|
-
- **[Common Mistakes](sdk-users/validation/common-mistakes.md)**: Error patterns and solutions
|
436
|
-
- **[Performance Guide](sdk-users/performance/)**: Optimization patterns
|
437
|
+
- **[Cheatsheet](sdk-users/2-core-concepts/cheatsheet/)**: 53 copy-paste patterns
|
438
|
+
- **[Common Mistakes](sdk-users/2-core-concepts/validation/common-mistakes.md)**: Error patterns and solutions
|
439
|
+
- **[Performance Guide](sdk-users/5-enterprise/performance/)**: Optimization patterns
|
437
440
|
|
438
441
|
## 🚢 Production Deployment
|
439
442
|
|