kailash 0.3.2__py3-none-any.whl → 0.4.1__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 (151) hide show
  1. kailash/__init__.py +33 -1
  2. kailash/access_control/__init__.py +129 -0
  3. kailash/access_control/managers.py +461 -0
  4. kailash/access_control/rule_evaluators.py +467 -0
  5. kailash/access_control_abac.py +825 -0
  6. kailash/config/__init__.py +27 -0
  7. kailash/config/database_config.py +359 -0
  8. kailash/database/__init__.py +28 -0
  9. kailash/database/execution_pipeline.py +499 -0
  10. kailash/middleware/__init__.py +306 -0
  11. kailash/middleware/auth/__init__.py +33 -0
  12. kailash/middleware/auth/access_control.py +436 -0
  13. kailash/middleware/auth/auth_manager.py +422 -0
  14. kailash/middleware/auth/jwt_auth.py +477 -0
  15. kailash/middleware/auth/kailash_jwt_auth.py +616 -0
  16. kailash/middleware/communication/__init__.py +37 -0
  17. kailash/middleware/communication/ai_chat.py +989 -0
  18. kailash/middleware/communication/api_gateway.py +802 -0
  19. kailash/middleware/communication/events.py +470 -0
  20. kailash/middleware/communication/realtime.py +710 -0
  21. kailash/middleware/core/__init__.py +21 -0
  22. kailash/middleware/core/agent_ui.py +890 -0
  23. kailash/middleware/core/schema.py +643 -0
  24. kailash/middleware/core/workflows.py +396 -0
  25. kailash/middleware/database/__init__.py +63 -0
  26. kailash/middleware/database/base.py +113 -0
  27. kailash/middleware/database/base_models.py +525 -0
  28. kailash/middleware/database/enums.py +106 -0
  29. kailash/middleware/database/migrations.py +12 -0
  30. kailash/{api/database.py → middleware/database/models.py} +183 -291
  31. kailash/middleware/database/repositories.py +685 -0
  32. kailash/middleware/database/session_manager.py +19 -0
  33. kailash/middleware/mcp/__init__.py +38 -0
  34. kailash/middleware/mcp/client_integration.py +585 -0
  35. kailash/middleware/mcp/enhanced_server.py +576 -0
  36. kailash/nodes/__init__.py +27 -3
  37. kailash/nodes/admin/__init__.py +42 -0
  38. kailash/nodes/admin/audit_log.py +794 -0
  39. kailash/nodes/admin/permission_check.py +864 -0
  40. kailash/nodes/admin/role_management.py +823 -0
  41. kailash/nodes/admin/security_event.py +1523 -0
  42. kailash/nodes/admin/user_management.py +944 -0
  43. kailash/nodes/ai/a2a.py +24 -7
  44. kailash/nodes/ai/ai_providers.py +248 -40
  45. kailash/nodes/ai/embedding_generator.py +11 -11
  46. kailash/nodes/ai/intelligent_agent_orchestrator.py +99 -11
  47. kailash/nodes/ai/llm_agent.py +436 -5
  48. kailash/nodes/ai/self_organizing.py +85 -10
  49. kailash/nodes/ai/vision_utils.py +148 -0
  50. kailash/nodes/alerts/__init__.py +26 -0
  51. kailash/nodes/alerts/base.py +234 -0
  52. kailash/nodes/alerts/discord.py +499 -0
  53. kailash/nodes/api/auth.py +287 -6
  54. kailash/nodes/api/rest.py +151 -0
  55. kailash/nodes/auth/__init__.py +17 -0
  56. kailash/nodes/auth/directory_integration.py +1228 -0
  57. kailash/nodes/auth/enterprise_auth_provider.py +1328 -0
  58. kailash/nodes/auth/mfa.py +2338 -0
  59. kailash/nodes/auth/risk_assessment.py +872 -0
  60. kailash/nodes/auth/session_management.py +1093 -0
  61. kailash/nodes/auth/sso.py +1040 -0
  62. kailash/nodes/base.py +344 -13
  63. kailash/nodes/base_cycle_aware.py +4 -2
  64. kailash/nodes/base_with_acl.py +1 -1
  65. kailash/nodes/code/python.py +283 -10
  66. kailash/nodes/compliance/__init__.py +9 -0
  67. kailash/nodes/compliance/data_retention.py +1888 -0
  68. kailash/nodes/compliance/gdpr.py +2004 -0
  69. kailash/nodes/data/__init__.py +22 -2
  70. kailash/nodes/data/async_connection.py +469 -0
  71. kailash/nodes/data/async_sql.py +757 -0
  72. kailash/nodes/data/async_vector.py +598 -0
  73. kailash/nodes/data/readers.py +767 -0
  74. kailash/nodes/data/retrieval.py +360 -1
  75. kailash/nodes/data/sharepoint_graph.py +397 -21
  76. kailash/nodes/data/sql.py +94 -5
  77. kailash/nodes/data/streaming.py +68 -8
  78. kailash/nodes/data/vector_db.py +54 -4
  79. kailash/nodes/enterprise/__init__.py +13 -0
  80. kailash/nodes/enterprise/batch_processor.py +741 -0
  81. kailash/nodes/enterprise/data_lineage.py +497 -0
  82. kailash/nodes/logic/convergence.py +31 -9
  83. kailash/nodes/logic/operations.py +14 -3
  84. kailash/nodes/mixins/__init__.py +8 -0
  85. kailash/nodes/mixins/event_emitter.py +201 -0
  86. kailash/nodes/mixins/mcp.py +9 -4
  87. kailash/nodes/mixins/security.py +165 -0
  88. kailash/nodes/monitoring/__init__.py +7 -0
  89. kailash/nodes/monitoring/performance_benchmark.py +2497 -0
  90. kailash/nodes/rag/__init__.py +284 -0
  91. kailash/nodes/rag/advanced.py +1615 -0
  92. kailash/nodes/rag/agentic.py +773 -0
  93. kailash/nodes/rag/conversational.py +999 -0
  94. kailash/nodes/rag/evaluation.py +875 -0
  95. kailash/nodes/rag/federated.py +1188 -0
  96. kailash/nodes/rag/graph.py +721 -0
  97. kailash/nodes/rag/multimodal.py +671 -0
  98. kailash/nodes/rag/optimized.py +933 -0
  99. kailash/nodes/rag/privacy.py +1059 -0
  100. kailash/nodes/rag/query_processing.py +1335 -0
  101. kailash/nodes/rag/realtime.py +764 -0
  102. kailash/nodes/rag/registry.py +547 -0
  103. kailash/nodes/rag/router.py +837 -0
  104. kailash/nodes/rag/similarity.py +1854 -0
  105. kailash/nodes/rag/strategies.py +566 -0
  106. kailash/nodes/rag/workflows.py +575 -0
  107. kailash/nodes/security/__init__.py +19 -0
  108. kailash/nodes/security/abac_evaluator.py +1411 -0
  109. kailash/nodes/security/audit_log.py +103 -0
  110. kailash/nodes/security/behavior_analysis.py +1893 -0
  111. kailash/nodes/security/credential_manager.py +401 -0
  112. kailash/nodes/security/rotating_credentials.py +760 -0
  113. kailash/nodes/security/security_event.py +133 -0
  114. kailash/nodes/security/threat_detection.py +1103 -0
  115. kailash/nodes/testing/__init__.py +9 -0
  116. kailash/nodes/testing/credential_testing.py +499 -0
  117. kailash/nodes/transform/__init__.py +10 -2
  118. kailash/nodes/transform/chunkers.py +592 -1
  119. kailash/nodes/transform/processors.py +484 -14
  120. kailash/nodes/validation.py +321 -0
  121. kailash/runtime/access_controlled.py +1 -1
  122. kailash/runtime/async_local.py +41 -7
  123. kailash/runtime/docker.py +1 -1
  124. kailash/runtime/local.py +474 -55
  125. kailash/runtime/parallel.py +1 -1
  126. kailash/runtime/parallel_cyclic.py +1 -1
  127. kailash/runtime/testing.py +210 -2
  128. kailash/security.py +1 -1
  129. kailash/utils/migrations/__init__.py +25 -0
  130. kailash/utils/migrations/generator.py +433 -0
  131. kailash/utils/migrations/models.py +231 -0
  132. kailash/utils/migrations/runner.py +489 -0
  133. kailash/utils/secure_logging.py +342 -0
  134. kailash/workflow/__init__.py +16 -0
  135. kailash/workflow/cyclic_runner.py +3 -4
  136. kailash/workflow/graph.py +70 -2
  137. kailash/workflow/resilience.py +249 -0
  138. kailash/workflow/templates.py +726 -0
  139. {kailash-0.3.2.dist-info → kailash-0.4.1.dist-info}/METADATA +256 -20
  140. kailash-0.4.1.dist-info/RECORD +227 -0
  141. kailash/api/__init__.py +0 -17
  142. kailash/api/__main__.py +0 -6
  143. kailash/api/studio_secure.py +0 -893
  144. kailash/mcp/__main__.py +0 -13
  145. kailash/mcp/server_new.py +0 -336
  146. kailash/mcp/servers/__init__.py +0 -12
  147. kailash-0.3.2.dist-info/RECORD +0 -136
  148. {kailash-0.3.2.dist-info → kailash-0.4.1.dist-info}/WHEEL +0 -0
  149. {kailash-0.3.2.dist-info → kailash-0.4.1.dist-info}/entry_points.txt +0 -0
  150. {kailash-0.3.2.dist-info → kailash-0.4.1.dist-info}/licenses/LICENSE +0 -0
  151. {kailash-0.3.2.dist-info → kailash-0.4.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,249 @@
1
+ """Resilience features for Kailash workflows.
2
+
3
+ This module provides resilience patterns that can be applied to any workflow,
4
+ including retry policies, fallback nodes, and circuit breakers.
5
+ """
6
+
7
+ import asyncio
8
+ import time
9
+ from dataclasses import dataclass, field
10
+ from datetime import datetime
11
+ from enum import Enum
12
+ from typing import Any, Callable, Dict, List, Optional, Union
13
+
14
+
15
+ class RetryStrategy(Enum):
16
+ """Retry strategies for failed nodes."""
17
+
18
+ IMMEDIATE = "immediate"
19
+ LINEAR = "linear"
20
+ EXPONENTIAL = "exponential"
21
+ FIBONACCI = "fibonacci"
22
+
23
+
24
+ @dataclass
25
+ class RetryPolicy:
26
+ """Configuration for node retry behavior."""
27
+
28
+ max_retries: int = 3
29
+ strategy: RetryStrategy = RetryStrategy.EXPONENTIAL
30
+ base_delay: float = 1.0
31
+ max_delay: float = 60.0
32
+ retry_on: List[type] = field(default_factory=lambda: [Exception])
33
+
34
+ def calculate_delay(self, attempt: int) -> float:
35
+ """Calculate delay based on retry strategy."""
36
+ if self.strategy == RetryStrategy.IMMEDIATE:
37
+ return 0
38
+ elif self.strategy == RetryStrategy.LINEAR:
39
+ delay = self.base_delay * attempt
40
+ elif self.strategy == RetryStrategy.EXPONENTIAL:
41
+ delay = self.base_delay * (2 ** (attempt - 1))
42
+ elif self.strategy == RetryStrategy.FIBONACCI:
43
+ # Fibonacci sequence
44
+ fib = [1, 1]
45
+ for _ in range(attempt - 1):
46
+ fib.append(fib[-1] + fib[-2])
47
+ delay = self.base_delay * fib[min(attempt - 1, len(fib) - 1)]
48
+ else:
49
+ delay = self.base_delay
50
+
51
+ return min(delay, self.max_delay)
52
+
53
+
54
+ @dataclass
55
+ class CircuitBreakerConfig:
56
+ """Configuration for circuit breaker pattern."""
57
+
58
+ failure_threshold: int = 5
59
+ success_threshold: int = 2
60
+ timeout: float = 60.0
61
+
62
+ # Runtime state
63
+ failures: int = 0
64
+ successes: int = 0
65
+ state: str = "closed" # closed, open, half-open
66
+ last_failure_time: Optional[float] = None
67
+
68
+ def is_open(self) -> bool:
69
+ """Check if circuit breaker is open."""
70
+ if self.state == "closed":
71
+ return False
72
+
73
+ if self.state == "open":
74
+ # Check if timeout has passed
75
+ if self.last_failure_time:
76
+ elapsed = time.time() - self.last_failure_time
77
+ if elapsed >= self.timeout:
78
+ # Move to half-open state
79
+ self.state = "half-open"
80
+ self.successes = 0
81
+ return False
82
+ return True
83
+
84
+ # Half-open state
85
+ return False
86
+
87
+ def record_success(self):
88
+ """Record successful execution."""
89
+ self.failures = 0
90
+ self.successes += 1
91
+
92
+ # Close circuit if enough successes in half-open state
93
+ if self.state == "half-open" and self.successes >= self.success_threshold:
94
+ self.state = "closed"
95
+
96
+ def record_failure(self):
97
+ """Record failed execution."""
98
+ self.failures += 1
99
+ self.successes = 0
100
+ self.last_failure_time = time.time()
101
+
102
+ # Open circuit if threshold reached
103
+ if self.failures >= self.failure_threshold:
104
+ self.state = "open"
105
+
106
+
107
+ class WorkflowResilience:
108
+ """Mixin class to add resilience features to workflows."""
109
+
110
+ def __init__(self):
111
+ """Initialize resilience features."""
112
+ self._fallback_nodes: Dict[str, List[Any]] = {}
113
+ self._retry_policies: Dict[str, RetryPolicy] = {}
114
+ self._circuit_breakers: Dict[str, CircuitBreakerConfig] = {}
115
+ self._execution_history: List[Dict[str, Any]] = []
116
+ self._dead_letter_queue: List[Dict[str, Any]] = []
117
+ self._node_metrics: Dict[str, Dict[str, Any]] = {}
118
+
119
+ def configure_retry(
120
+ self,
121
+ node_id: str,
122
+ max_retries: int = 3,
123
+ strategy: RetryStrategy = RetryStrategy.EXPONENTIAL,
124
+ base_delay: float = 1.0,
125
+ max_delay: float = 60.0,
126
+ retry_on: Optional[List[type]] = None,
127
+ ):
128
+ """
129
+ Configure retry policy for a specific node.
130
+
131
+ Args:
132
+ node_id: Node to apply policy to
133
+ max_retries: Maximum retry attempts
134
+ strategy: Retry delay strategy
135
+ base_delay: Base delay in seconds
136
+ max_delay: Maximum delay in seconds
137
+ retry_on: List of exception types to retry on
138
+ """
139
+ self._retry_policies[node_id] = RetryPolicy(
140
+ max_retries=max_retries,
141
+ strategy=strategy,
142
+ base_delay=base_delay,
143
+ max_delay=max_delay,
144
+ retry_on=retry_on or [Exception],
145
+ )
146
+
147
+ def add_fallback(self, primary_node_id: str, fallback_node_id: str):
148
+ """
149
+ Add a fallback node for automatic failover.
150
+
151
+ Args:
152
+ primary_node_id: Primary node that might fail
153
+ fallback_node_id: Fallback node to use on failure
154
+ """
155
+ if primary_node_id not in self._fallback_nodes:
156
+ self._fallback_nodes[primary_node_id] = []
157
+
158
+ self._fallback_nodes[primary_node_id].append(fallback_node_id)
159
+
160
+ def configure_circuit_breaker(
161
+ self,
162
+ node_id: str,
163
+ failure_threshold: int = 5,
164
+ success_threshold: int = 2,
165
+ timeout: float = 60.0,
166
+ ):
167
+ """
168
+ Configure circuit breaker for a node.
169
+
170
+ Args:
171
+ node_id: Node to protect
172
+ failure_threshold: Failures before opening circuit
173
+ success_threshold: Successes needed to close circuit
174
+ timeout: Time before attempting to close circuit
175
+ """
176
+ self._circuit_breakers[node_id] = CircuitBreakerConfig(
177
+ failure_threshold=failure_threshold,
178
+ success_threshold=success_threshold,
179
+ timeout=timeout,
180
+ )
181
+
182
+ def get_resilience_metrics(self) -> Dict[str, Any]:
183
+ """Get execution metrics for monitoring."""
184
+ return {
185
+ "node_metrics": self._node_metrics,
186
+ "circuit_breakers": {
187
+ name: {
188
+ "state": breaker.state,
189
+ "failures": breaker.failures,
190
+ "last_failure": breaker.last_failure_time,
191
+ }
192
+ for name, breaker in self._circuit_breakers.items()
193
+ },
194
+ "dead_letter_queue_size": len(self._dead_letter_queue),
195
+ "retry_policies": {
196
+ name: {
197
+ "max_retries": policy.max_retries,
198
+ "strategy": policy.strategy.value,
199
+ }
200
+ for name, policy in self._retry_policies.items()
201
+ },
202
+ }
203
+
204
+ def get_dead_letter_queue(self) -> List[Dict[str, Any]]:
205
+ """Get failed executions for manual intervention."""
206
+ return self._dead_letter_queue
207
+
208
+ def clear_dead_letter_queue(self):
209
+ """Clear the dead letter queue after processing."""
210
+ self._dead_letter_queue = []
211
+
212
+ def reset_circuit_breaker(self, node_id: str):
213
+ """Manually reset a circuit breaker."""
214
+ if node_id in self._circuit_breakers:
215
+ breaker = self._circuit_breakers[node_id]
216
+ breaker.state = "closed"
217
+ breaker.failures = 0
218
+ breaker.successes = 0
219
+ breaker.last_failure_time = None
220
+
221
+
222
+ def apply_resilience_to_workflow(workflow_class):
223
+ """Decorator to add resilience features to a workflow class."""
224
+
225
+ # Store original methods
226
+ original_init = workflow_class.__init__
227
+
228
+ def new_init(self, *args, **kwargs):
229
+ # Call original init
230
+ original_init(self, *args, **kwargs)
231
+ # Initialize resilience attributes directly on instance
232
+ self._fallback_nodes = {}
233
+ self._retry_policies = {}
234
+ self._circuit_breakers = {}
235
+ self._execution_history = []
236
+ self._dead_letter_queue = []
237
+ self._node_metrics = {}
238
+
239
+ # Add resilience methods to the class
240
+ for attr_name in dir(WorkflowResilience):
241
+ if not attr_name.startswith("_"):
242
+ attr = getattr(WorkflowResilience, attr_name)
243
+ if callable(attr) and attr_name not in ["__init__"]:
244
+ setattr(workflow_class, attr_name, attr)
245
+
246
+ # Override __init__
247
+ workflow_class.__init__ = new_init
248
+
249
+ return workflow_class