kailash 0.8.3__py3-none-any.whl → 0.8.5__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 (84) hide show
  1. kailash/__init__.py +1 -7
  2. kailash/cli/__init__.py +11 -1
  3. kailash/cli/validation_audit.py +570 -0
  4. kailash/core/actors/supervisor.py +1 -1
  5. kailash/core/resilience/circuit_breaker.py +71 -1
  6. kailash/core/resilience/health_monitor.py +172 -0
  7. kailash/edge/compliance.py +33 -0
  8. kailash/edge/consistency.py +609 -0
  9. kailash/edge/coordination/__init__.py +30 -0
  10. kailash/edge/coordination/global_ordering.py +355 -0
  11. kailash/edge/coordination/leader_election.py +217 -0
  12. kailash/edge/coordination/partition_detector.py +296 -0
  13. kailash/edge/coordination/raft.py +485 -0
  14. kailash/edge/discovery.py +63 -1
  15. kailash/edge/migration/__init__.py +19 -0
  16. kailash/edge/migration/edge_migrator.py +832 -0
  17. kailash/edge/monitoring/__init__.py +21 -0
  18. kailash/edge/monitoring/edge_monitor.py +736 -0
  19. kailash/edge/prediction/__init__.py +10 -0
  20. kailash/edge/prediction/predictive_warmer.py +591 -0
  21. kailash/edge/resource/__init__.py +102 -0
  22. kailash/edge/resource/cloud_integration.py +796 -0
  23. kailash/edge/resource/cost_optimizer.py +949 -0
  24. kailash/edge/resource/docker_integration.py +919 -0
  25. kailash/edge/resource/kubernetes_integration.py +893 -0
  26. kailash/edge/resource/platform_integration.py +913 -0
  27. kailash/edge/resource/predictive_scaler.py +959 -0
  28. kailash/edge/resource/resource_analyzer.py +824 -0
  29. kailash/edge/resource/resource_pools.py +610 -0
  30. kailash/integrations/dataflow_edge.py +261 -0
  31. kailash/mcp_server/registry_integration.py +1 -1
  32. kailash/monitoring/__init__.py +18 -0
  33. kailash/monitoring/alerts.py +646 -0
  34. kailash/monitoring/metrics.py +677 -0
  35. kailash/nodes/__init__.py +2 -0
  36. kailash/nodes/ai/__init__.py +17 -0
  37. kailash/nodes/ai/a2a.py +1914 -43
  38. kailash/nodes/ai/a2a_backup.py +1807 -0
  39. kailash/nodes/ai/hybrid_search.py +972 -0
  40. kailash/nodes/ai/semantic_memory.py +558 -0
  41. kailash/nodes/ai/streaming_analytics.py +947 -0
  42. kailash/nodes/base.py +545 -0
  43. kailash/nodes/edge/__init__.py +36 -0
  44. kailash/nodes/edge/base.py +240 -0
  45. kailash/nodes/edge/cloud_node.py +710 -0
  46. kailash/nodes/edge/coordination.py +239 -0
  47. kailash/nodes/edge/docker_node.py +825 -0
  48. kailash/nodes/edge/edge_data.py +582 -0
  49. kailash/nodes/edge/edge_migration_node.py +392 -0
  50. kailash/nodes/edge/edge_monitoring_node.py +421 -0
  51. kailash/nodes/edge/edge_state.py +673 -0
  52. kailash/nodes/edge/edge_warming_node.py +393 -0
  53. kailash/nodes/edge/kubernetes_node.py +652 -0
  54. kailash/nodes/edge/platform_node.py +766 -0
  55. kailash/nodes/edge/resource_analyzer_node.py +378 -0
  56. kailash/nodes/edge/resource_optimizer_node.py +501 -0
  57. kailash/nodes/edge/resource_scaler_node.py +397 -0
  58. kailash/nodes/ports.py +676 -0
  59. kailash/runtime/local.py +344 -1
  60. kailash/runtime/validation/__init__.py +20 -0
  61. kailash/runtime/validation/connection_context.py +119 -0
  62. kailash/runtime/validation/enhanced_error_formatter.py +202 -0
  63. kailash/runtime/validation/error_categorizer.py +164 -0
  64. kailash/runtime/validation/metrics.py +380 -0
  65. kailash/runtime/validation/performance.py +615 -0
  66. kailash/runtime/validation/suggestion_engine.py +212 -0
  67. kailash/testing/fixtures.py +2 -2
  68. kailash/workflow/builder.py +234 -8
  69. kailash/workflow/contracts.py +418 -0
  70. kailash/workflow/edge_infrastructure.py +369 -0
  71. kailash/workflow/migration.py +3 -3
  72. kailash/workflow/type_inference.py +669 -0
  73. {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/METADATA +44 -27
  74. {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/RECORD +78 -28
  75. kailash/nexus/__init__.py +0 -21
  76. kailash/nexus/cli/__init__.py +0 -5
  77. kailash/nexus/cli/__main__.py +0 -6
  78. kailash/nexus/cli/main.py +0 -176
  79. kailash/nexus/factory.py +0 -413
  80. kailash/nexus/gateway.py +0 -545
  81. {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/WHEEL +0 -0
  82. {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/entry_points.txt +0 -0
  83. {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/licenses/LICENSE +0 -0
  84. {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,202 @@
1
+ """
2
+ Enhanced error message formatting for connection validation errors.
3
+
4
+ Formats validation errors into structured, readable messages with
5
+ connection paths, categorization, suggestions, and examples.
6
+ """
7
+
8
+ from typing import Optional
9
+
10
+ from .connection_context import ConnectionContext
11
+ from .error_categorizer import ErrorCategorizer, ErrorCategory
12
+ from .suggestion_engine import ValidationSuggestion
13
+
14
+
15
+ class EnhancedErrorFormatter:
16
+ """Formats validation errors into enhanced, actionable error messages."""
17
+
18
+ def __init__(self):
19
+ self.categorizer = ErrorCategorizer()
20
+
21
+ def format_enhanced_error(
22
+ self,
23
+ original_error: str,
24
+ error_category: ErrorCategory,
25
+ connection_context: ConnectionContext,
26
+ suggestion: Optional[ValidationSuggestion] = None,
27
+ ) -> str:
28
+ """Format a comprehensive error message with all enhancement details.
29
+
30
+ Args:
31
+ original_error: Original validation error message
32
+ error_category: Categorized error type
33
+ connection_context: Context about the failing connection
34
+ suggestion: Optional actionable suggestion
35
+
36
+ Returns:
37
+ Formatted error message with structured sections
38
+ """
39
+ sections = []
40
+
41
+ # Header with error category
42
+ category_desc = self.categorizer.get_category_description(error_category)
43
+ severity = self.categorizer.get_severity_level(error_category)
44
+
45
+ sections.append(f"🚨 Connection Validation Error: {category_desc} [{severity}]")
46
+ sections.append("=" * 60)
47
+
48
+ # Problem section
49
+ sections.append("\n📋 Problem:")
50
+ sections.append(f" {original_error}")
51
+
52
+ # Connection path section
53
+ sections.append("\n🔗 Connection:")
54
+ connection_path = connection_context.get_connection_path()
55
+ sections.append(f" {connection_path}")
56
+
57
+ # Parameter details (sanitized)
58
+ if not connection_context.is_security_sensitive():
59
+ value_repr = connection_context.get_sanitized_value()
60
+ sections.append(f" Value: {value_repr}")
61
+ else:
62
+ sections.append(" Value: **REDACTED** (security-sensitive)")
63
+
64
+ sections.append(f" Validation Mode: {connection_context.validation_mode}")
65
+
66
+ # Suggestion section
67
+ if suggestion:
68
+ sections.append("\n💡 Suggestion:")
69
+ sections.append(f" {suggestion.message}")
70
+
71
+ # Code example
72
+ if suggestion.code_example:
73
+ sections.append("\n📝 Example:")
74
+ example_lines = suggestion.code_example.split("\n")
75
+ for line in example_lines:
76
+ sections.append(f" {line}")
77
+
78
+ # Alternative approaches
79
+ if suggestion.alternative_approaches:
80
+ sections.append("\n🔄 Alternatives:")
81
+ for i, alt in enumerate(suggestion.alternative_approaches, 1):
82
+ sections.append(f" {i}. {alt}")
83
+
84
+ # Documentation link
85
+ if suggestion.documentation_link:
86
+ sections.append("\n📚 Documentation:")
87
+ sections.append(f" {suggestion.documentation_link}")
88
+ else:
89
+ sections.append("\n💡 Suggestion:")
90
+ sections.append(" Check node documentation for parameter requirements.")
91
+ sections.append(" Verify data types and connection mapping.")
92
+
93
+ # Troubleshooting tips
94
+ sections.append("\n🛠️ Quick Troubleshooting:")
95
+ sections.append(" 1. Check the source node output format")
96
+ sections.append(" 2. Verify target node parameter requirements")
97
+ sections.append(" 3. Test with simplified data first")
98
+ sections.append(
99
+ " 4. Review connection syntax: workflow.add_connection(source, source_port, target, target_port)"
100
+ )
101
+
102
+ return "\n".join(sections)
103
+
104
+ def format_simple_error(
105
+ self, original_error: str, connection_context: ConnectionContext
106
+ ) -> str:
107
+ """Format a simple enhanced error message for warn mode.
108
+
109
+ Args:
110
+ original_error: Original validation error message
111
+ connection_context: Context about the failing connection
112
+
113
+ Returns:
114
+ Simple formatted error message
115
+ """
116
+ connection_path = connection_context.get_connection_path()
117
+ return f"Connection validation warning: {connection_path} - {original_error}"
118
+
119
+ def format_security_error(
120
+ self,
121
+ original_error: str,
122
+ connection_context: ConnectionContext,
123
+ suggestion: Optional[ValidationSuggestion] = None,
124
+ ) -> str:
125
+ """Format security-specific error message with appropriate warnings.
126
+
127
+ Args:
128
+ original_error: Original security error message
129
+ connection_context: Context about the failing connection
130
+ suggestion: Optional security-specific suggestion
131
+
132
+ Returns:
133
+ Security-focused error message
134
+ """
135
+ sections = []
136
+
137
+ sections.append("🔒 SECURITY ALERT: Potential Security Vulnerability")
138
+ sections.append("=" * 60)
139
+
140
+ sections.append("\n⚠️ Security Issue:")
141
+ sections.append(f" {original_error}")
142
+
143
+ sections.append("\n🔗 Affected Connection:")
144
+ connection_path = connection_context.get_connection_path()
145
+ sections.append(f" {connection_path}")
146
+
147
+ # Always redact security-sensitive values
148
+ sections.append(" Value: **REDACTED** (potential security risk)")
149
+
150
+ if suggestion:
151
+ sections.append("\n🛡️ Security Recommendation:")
152
+ sections.append(f" {suggestion.message}")
153
+
154
+ if suggestion.code_example:
155
+ sections.append("\n🔐 Secure Example:")
156
+ example_lines = suggestion.code_example.split("\n")
157
+ for line in example_lines:
158
+ sections.append(f" {line}")
159
+
160
+ sections.append("\n🚨 Immediate Actions:")
161
+ sections.append(" 1. Review the data source for potential attacks")
162
+ sections.append(" 2. Implement input validation and sanitization")
163
+ sections.append(" 3. Use parameterized queries for database operations")
164
+ sections.append(" 4. Consider implementing rate limiting")
165
+
166
+ sections.append("\n📋 Security Checklist:")
167
+ sections.append(" □ Input validation implemented")
168
+ sections.append(" □ Output encoding applied")
169
+ sections.append(" □ Parameterized queries used")
170
+ sections.append(" □ Access controls verified")
171
+
172
+ return "\n".join(sections)
173
+
174
+ def get_error_summary(
175
+ self, error_category: ErrorCategory, connection_context: ConnectionContext
176
+ ) -> str:
177
+ """Get a brief summary of the error for logging.
178
+
179
+ Args:
180
+ error_category: Categorized error type
181
+ connection_context: Context about the failing connection
182
+
183
+ Returns:
184
+ Brief error summary
185
+ """
186
+ category_desc = self.categorizer.get_category_description(error_category)
187
+ connection_path = connection_context.get_connection_path()
188
+
189
+ return f"{category_desc}: {connection_path}"
190
+
191
+ def _indent_lines(self, text: str, indent: str = " ") -> str:
192
+ """Indent all lines in text with the given prefix.
193
+
194
+ Args:
195
+ text: Text to indent
196
+ indent: Indentation string
197
+
198
+ Returns:
199
+ Indented text
200
+ """
201
+ lines = text.split("\n")
202
+ return "\n".join(f"{indent}{line}" for line in lines)
@@ -0,0 +1,164 @@
1
+ """
2
+ Error categorization for connection validation failures.
3
+
4
+ Classifies validation errors into specific categories to enable
5
+ targeted suggestion generation and better error handling.
6
+ """
7
+
8
+ import re
9
+ from enum import Enum
10
+ from typing import Any, Optional
11
+
12
+
13
+ class ErrorCategory(Enum):
14
+ """Categories of connection validation errors."""
15
+
16
+ TYPE_MISMATCH = "type_mismatch"
17
+ """Parameter type doesn't match expected type"""
18
+
19
+ MISSING_PARAMETER = "missing_parameter"
20
+ """Required parameter is missing or None"""
21
+
22
+ CONSTRAINT_VIOLATION = "constraint_violation"
23
+ """Parameter violates validation constraints (range, format, etc.)"""
24
+
25
+ SECURITY_VIOLATION = "security_violation"
26
+ """Parameter contains potential security issues (injection, etc.)"""
27
+
28
+ UNKNOWN = "unknown"
29
+ """Error category could not be determined"""
30
+
31
+
32
+ class ErrorCategorizer:
33
+ """Categorizes validation errors for enhanced error message generation."""
34
+
35
+ # Error patterns for categorization
36
+ TYPE_ERROR_PATTERNS = [
37
+ r"expected .+ but got .+",
38
+ r"object of type .+ has no attribute",
39
+ r"unsupported operand type",
40
+ r"can't convert .+ to .+",
41
+ r"'[^']+' object .+ not .+",
42
+ r"argument must be .+, not .+",
43
+ ]
44
+
45
+ MISSING_PARAMETER_PATTERNS = [
46
+ r"missing required parameter",
47
+ r"required argument .+ is missing",
48
+ r"takes .+ arguments but .+ were given",
49
+ r"missing .+ required",
50
+ r"parameter .+ is required",
51
+ ]
52
+
53
+ CONSTRAINT_VIOLATION_PATTERNS = [
54
+ r"must be positive",
55
+ r"must be greater than",
56
+ r"must be less than",
57
+ r"invalid value",
58
+ r"out of range",
59
+ r"violates constraint",
60
+ r"exceeds maximum",
61
+ r"below minimum",
62
+ ]
63
+
64
+ SECURITY_VIOLATION_PATTERNS = [
65
+ r"sql injection",
66
+ r"injection detected",
67
+ r"security violation",
68
+ r"potential attack",
69
+ r"malicious",
70
+ r"dangerous",
71
+ r"unsafe",
72
+ r"script injection",
73
+ ]
74
+
75
+ def categorize_error(
76
+ self, error: Exception, node_type: Optional[str] = None
77
+ ) -> ErrorCategory:
78
+ """Categorize a validation error based on error message and context.
79
+
80
+ Args:
81
+ error: The validation error exception
82
+ node_type: Optional node type for additional context
83
+
84
+ Returns:
85
+ ErrorCategory enum value indicating the error type
86
+ """
87
+ error_message = str(error).lower()
88
+ error_type = type(error).__name__
89
+
90
+ # Check for security violations first (highest priority)
91
+ if self._matches_patterns(error_message, self.SECURITY_VIOLATION_PATTERNS):
92
+ return ErrorCategory.SECURITY_VIOLATION
93
+
94
+ # Check for type errors
95
+ if error_type in ["TypeError", "AttributeError"] or self._matches_patterns(
96
+ error_message, self.TYPE_ERROR_PATTERNS
97
+ ):
98
+ return ErrorCategory.TYPE_MISMATCH
99
+
100
+ # Check for missing parameter errors
101
+ if error_type in ["ValueError", "TypeError"] and self._matches_patterns(
102
+ error_message, self.MISSING_PARAMETER_PATTERNS
103
+ ):
104
+ return ErrorCategory.MISSING_PARAMETER
105
+
106
+ # Check for constraint violations
107
+ if error_type == "ValueError" and self._matches_patterns(
108
+ error_message, self.CONSTRAINT_VIOLATION_PATTERNS
109
+ ):
110
+ return ErrorCategory.CONSTRAINT_VIOLATION
111
+
112
+ # Default to unknown if no pattern matches
113
+ return ErrorCategory.UNKNOWN
114
+
115
+ def _matches_patterns(self, text: str, patterns: list[str]) -> bool:
116
+ """Check if text matches any of the given regex patterns.
117
+
118
+ Args:
119
+ text: Text to check
120
+ patterns: List of regex patterns
121
+
122
+ Returns:
123
+ True if text matches any pattern
124
+ """
125
+ for pattern in patterns:
126
+ if re.search(pattern, text, re.IGNORECASE):
127
+ return True
128
+ return False
129
+
130
+ def get_category_description(self, category: ErrorCategory) -> str:
131
+ """Get human-readable description of error category.
132
+
133
+ Args:
134
+ category: Error category enum
135
+
136
+ Returns:
137
+ Human-readable description
138
+ """
139
+ descriptions = {
140
+ ErrorCategory.TYPE_MISMATCH: "Type Mismatch",
141
+ ErrorCategory.MISSING_PARAMETER: "Missing Required Parameter",
142
+ ErrorCategory.CONSTRAINT_VIOLATION: "Parameter Constraint Violation",
143
+ ErrorCategory.SECURITY_VIOLATION: "Security Violation",
144
+ ErrorCategory.UNKNOWN: "Unknown Validation Error",
145
+ }
146
+ return descriptions.get(category, "Unknown Error")
147
+
148
+ def get_severity_level(self, category: ErrorCategory) -> str:
149
+ """Get severity level for error category.
150
+
151
+ Args:
152
+ category: Error category enum
153
+
154
+ Returns:
155
+ Severity level: 'CRITICAL', 'HIGH', 'MEDIUM', 'LOW'
156
+ """
157
+ severity_map = {
158
+ ErrorCategory.SECURITY_VIOLATION: "CRITICAL",
159
+ ErrorCategory.MISSING_PARAMETER: "HIGH",
160
+ ErrorCategory.TYPE_MISMATCH: "MEDIUM",
161
+ ErrorCategory.CONSTRAINT_VIOLATION: "MEDIUM",
162
+ ErrorCategory.UNKNOWN: "LOW",
163
+ }
164
+ return severity_map.get(category, "LOW")