kailash 0.3.1__py3-none-any.whl → 0.4.0__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 (146) 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 +25 -3
  37. kailash/nodes/admin/__init__.py +35 -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 +1519 -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 +1 -0
  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 +407 -2
  48. kailash/nodes/ai/self_organizing.py +85 -10
  49. kailash/nodes/api/auth.py +287 -6
  50. kailash/nodes/api/rest.py +151 -0
  51. kailash/nodes/auth/__init__.py +17 -0
  52. kailash/nodes/auth/directory_integration.py +1228 -0
  53. kailash/nodes/auth/enterprise_auth_provider.py +1328 -0
  54. kailash/nodes/auth/mfa.py +2338 -0
  55. kailash/nodes/auth/risk_assessment.py +872 -0
  56. kailash/nodes/auth/session_management.py +1093 -0
  57. kailash/nodes/auth/sso.py +1040 -0
  58. kailash/nodes/base.py +344 -13
  59. kailash/nodes/base_cycle_aware.py +4 -2
  60. kailash/nodes/base_with_acl.py +1 -1
  61. kailash/nodes/code/python.py +293 -12
  62. kailash/nodes/compliance/__init__.py +9 -0
  63. kailash/nodes/compliance/data_retention.py +1888 -0
  64. kailash/nodes/compliance/gdpr.py +2004 -0
  65. kailash/nodes/data/__init__.py +22 -2
  66. kailash/nodes/data/async_connection.py +469 -0
  67. kailash/nodes/data/async_sql.py +757 -0
  68. kailash/nodes/data/async_vector.py +598 -0
  69. kailash/nodes/data/readers.py +767 -0
  70. kailash/nodes/data/retrieval.py +360 -1
  71. kailash/nodes/data/sharepoint_graph.py +397 -21
  72. kailash/nodes/data/sql.py +94 -5
  73. kailash/nodes/data/streaming.py +68 -8
  74. kailash/nodes/data/vector_db.py +54 -4
  75. kailash/nodes/enterprise/__init__.py +13 -0
  76. kailash/nodes/enterprise/batch_processor.py +741 -0
  77. kailash/nodes/enterprise/data_lineage.py +497 -0
  78. kailash/nodes/logic/convergence.py +31 -9
  79. kailash/nodes/logic/operations.py +14 -3
  80. kailash/nodes/mixins/__init__.py +8 -0
  81. kailash/nodes/mixins/event_emitter.py +201 -0
  82. kailash/nodes/mixins/mcp.py +9 -4
  83. kailash/nodes/mixins/security.py +165 -0
  84. kailash/nodes/monitoring/__init__.py +7 -0
  85. kailash/nodes/monitoring/performance_benchmark.py +2497 -0
  86. kailash/nodes/rag/__init__.py +284 -0
  87. kailash/nodes/rag/advanced.py +1615 -0
  88. kailash/nodes/rag/agentic.py +773 -0
  89. kailash/nodes/rag/conversational.py +999 -0
  90. kailash/nodes/rag/evaluation.py +875 -0
  91. kailash/nodes/rag/federated.py +1188 -0
  92. kailash/nodes/rag/graph.py +721 -0
  93. kailash/nodes/rag/multimodal.py +671 -0
  94. kailash/nodes/rag/optimized.py +933 -0
  95. kailash/nodes/rag/privacy.py +1059 -0
  96. kailash/nodes/rag/query_processing.py +1335 -0
  97. kailash/nodes/rag/realtime.py +764 -0
  98. kailash/nodes/rag/registry.py +547 -0
  99. kailash/nodes/rag/router.py +837 -0
  100. kailash/nodes/rag/similarity.py +1854 -0
  101. kailash/nodes/rag/strategies.py +566 -0
  102. kailash/nodes/rag/workflows.py +575 -0
  103. kailash/nodes/security/__init__.py +19 -0
  104. kailash/nodes/security/abac_evaluator.py +1411 -0
  105. kailash/nodes/security/audit_log.py +91 -0
  106. kailash/nodes/security/behavior_analysis.py +1893 -0
  107. kailash/nodes/security/credential_manager.py +401 -0
  108. kailash/nodes/security/rotating_credentials.py +760 -0
  109. kailash/nodes/security/security_event.py +132 -0
  110. kailash/nodes/security/threat_detection.py +1103 -0
  111. kailash/nodes/testing/__init__.py +9 -0
  112. kailash/nodes/testing/credential_testing.py +499 -0
  113. kailash/nodes/transform/__init__.py +10 -2
  114. kailash/nodes/transform/chunkers.py +592 -1
  115. kailash/nodes/transform/processors.py +484 -14
  116. kailash/nodes/validation.py +321 -0
  117. kailash/runtime/access_controlled.py +1 -1
  118. kailash/runtime/async_local.py +41 -7
  119. kailash/runtime/docker.py +1 -1
  120. kailash/runtime/local.py +474 -55
  121. kailash/runtime/parallel.py +1 -1
  122. kailash/runtime/parallel_cyclic.py +1 -1
  123. kailash/runtime/testing.py +210 -2
  124. kailash/utils/migrations/__init__.py +25 -0
  125. kailash/utils/migrations/generator.py +433 -0
  126. kailash/utils/migrations/models.py +231 -0
  127. kailash/utils/migrations/runner.py +489 -0
  128. kailash/utils/secure_logging.py +342 -0
  129. kailash/workflow/__init__.py +16 -0
  130. kailash/workflow/cyclic_runner.py +3 -4
  131. kailash/workflow/graph.py +70 -2
  132. kailash/workflow/resilience.py +249 -0
  133. kailash/workflow/templates.py +726 -0
  134. {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/METADATA +253 -20
  135. kailash-0.4.0.dist-info/RECORD +223 -0
  136. kailash/api/__init__.py +0 -17
  137. kailash/api/__main__.py +0 -6
  138. kailash/api/studio_secure.py +0 -893
  139. kailash/mcp/__main__.py +0 -13
  140. kailash/mcp/server_new.py +0 -336
  141. kailash/mcp/servers/__init__.py +0 -12
  142. kailash-0.3.1.dist-info/RECORD +0 -136
  143. {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/WHEEL +0 -0
  144. {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/entry_points.txt +0 -0
  145. {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/licenses/LICENSE +0 -0
  146. {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,201 @@
1
+ """
2
+ Event Emitter Mixin for Nodes
3
+
4
+ Provides event emission capabilities for nodes to integrate with the
5
+ middleware layer for real-time monitoring and communication.
6
+ """
7
+
8
+ import logging
9
+ from typing import TYPE_CHECKING, Any, Dict, Optional
10
+
11
+ if TYPE_CHECKING:
12
+ from kailash.middleware.events import EventStream
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class EventEmitterMixin:
18
+ """
19
+ Mixin that adds event emission capabilities to nodes.
20
+
21
+ This mixin allows nodes to emit events that can be consumed by the
22
+ middleware layer for real-time monitoring, logging, and frontend updates.
23
+ """
24
+
25
+ def __init__(self, *args, **kwargs):
26
+ super().__init__(*args, **kwargs)
27
+ self._event_stream: Optional["EventStream"] = None
28
+ self._session_id: Optional[str] = None
29
+ self._workflow_id: Optional[str] = None
30
+ self._execution_id: Optional[str] = None
31
+
32
+ def set_event_context(
33
+ self,
34
+ event_stream: "EventStream",
35
+ session_id: str = None,
36
+ workflow_id: str = None,
37
+ execution_id: str = None,
38
+ ):
39
+ """Set the event context for this node."""
40
+ self._event_stream = event_stream
41
+ self._session_id = session_id
42
+ self._workflow_id = workflow_id
43
+ self._execution_id = execution_id
44
+
45
+ async def emit_node_started(self, inputs: Dict[str, Any] = None):
46
+ """Emit node started event."""
47
+ if self._event_stream:
48
+ try:
49
+ from kailash.middleware.events import EventType, NodeEvent
50
+
51
+ event = NodeEvent(
52
+ type=EventType.NODE_STARTED,
53
+ workflow_id=self._workflow_id,
54
+ node_id=getattr(self, "name", "unknown"),
55
+ node_type=self.__class__.__name__,
56
+ node_name=getattr(self, "name", "unknown"),
57
+ inputs=inputs or {},
58
+ session_id=self._session_id,
59
+ )
60
+
61
+ await self._event_stream.emit(event)
62
+ except Exception as e:
63
+ logger.warning(f"Failed to emit node started event: {e}")
64
+
65
+ async def emit_node_completed(
66
+ self, outputs: Dict[str, Any] = None, execution_time_ms: float = None
67
+ ):
68
+ """Emit node completed event."""
69
+ if self._event_stream:
70
+ try:
71
+ from kailash.middleware.events import EventType, NodeEvent
72
+
73
+ event = NodeEvent(
74
+ type=EventType.NODE_COMPLETED,
75
+ workflow_id=self._workflow_id,
76
+ node_id=getattr(self, "name", "unknown"),
77
+ node_type=self.__class__.__name__,
78
+ node_name=getattr(self, "name", "unknown"),
79
+ outputs=outputs or {},
80
+ execution_time_ms=execution_time_ms,
81
+ session_id=self._session_id,
82
+ )
83
+
84
+ await self._event_stream.emit(event)
85
+ except Exception as e:
86
+ logger.warning(f"Failed to emit node completed event: {e}")
87
+
88
+ async def emit_node_failed(self, error: str):
89
+ """Emit node failed event."""
90
+ if self._event_stream:
91
+ try:
92
+ from kailash.middleware.events import EventType, NodeEvent
93
+
94
+ event = NodeEvent(
95
+ type=EventType.NODE_FAILED,
96
+ workflow_id=self._workflow_id,
97
+ node_id=getattr(self, "name", "unknown"),
98
+ node_type=self.__class__.__name__,
99
+ node_name=getattr(self, "name", "unknown"),
100
+ error=error,
101
+ session_id=self._session_id,
102
+ )
103
+
104
+ await self._event_stream.emit(event)
105
+ except Exception as e:
106
+ logger.warning(f"Failed to emit node failed event: {e}")
107
+
108
+ async def emit_node_progress(self, progress_percent: float, message: str = None):
109
+ """Emit node progress event."""
110
+ if self._event_stream:
111
+ try:
112
+ from kailash.middleware.events import EventType, NodeEvent
113
+
114
+ event = NodeEvent(
115
+ type=EventType.NODE_PROGRESS,
116
+ workflow_id=self._workflow_id,
117
+ node_id=getattr(self, "name", "unknown"),
118
+ node_type=self.__class__.__name__,
119
+ node_name=getattr(self, "name", "unknown"),
120
+ metadata={"progress_percent": progress_percent, "message": message},
121
+ session_id=self._session_id,
122
+ )
123
+
124
+ await self._event_stream.emit(event)
125
+ except Exception as e:
126
+ logger.warning(f"Failed to emit node progress event: {e}")
127
+
128
+ def has_event_stream(self) -> bool:
129
+ """Check if event stream is available."""
130
+ return self._event_stream is not None
131
+
132
+
133
+ class EventAwareNode:
134
+ """
135
+ Enhanced node base class with built-in event emission.
136
+
137
+ This class can be used as a base class for nodes that want
138
+ automatic event emission during execution.
139
+ """
140
+
141
+ def __init__(self, *args, **kwargs):
142
+ # Initialize the mixin first
143
+ if hasattr(super(), "__init__"):
144
+ super().__init__(*args, **kwargs)
145
+
146
+ # Add event emission capabilities
147
+ self._event_mixin = EventEmitterMixin()
148
+
149
+ def set_event_context(self, *args, **kwargs):
150
+ """Delegate to mixin."""
151
+ self._event_mixin.set_event_context(*args, **kwargs)
152
+
153
+ async def emit_node_started(self, *args, **kwargs):
154
+ """Delegate to mixin."""
155
+ await self._event_mixin.emit_node_started(*args, **kwargs)
156
+
157
+ async def emit_node_completed(self, *args, **kwargs):
158
+ """Delegate to mixin."""
159
+ await self._event_mixin.emit_node_completed(*args, **kwargs)
160
+
161
+ async def emit_node_failed(self, *args, **kwargs):
162
+ """Delegate to mixin."""
163
+ await self._event_mixin.emit_node_failed(*args, **kwargs)
164
+
165
+ async def emit_node_progress(self, *args, **kwargs):
166
+ """Delegate to mixin."""
167
+ await self._event_mixin.emit_node_progress(*args, **kwargs)
168
+
169
+ def has_event_stream(self) -> bool:
170
+ """Delegate to mixin."""
171
+ return self._event_mixin.has_event_stream()
172
+
173
+
174
+ def enable_events_for_node(node_instance, event_stream, **context):
175
+ """
176
+ Enable events for a node instance.
177
+
178
+ This function can be used to add event capabilities to existing
179
+ node instances without requiring them to inherit from EventAwareNode.
180
+
181
+ Args:
182
+ node_instance: The node instance to enhance
183
+ event_stream: The event stream to use
184
+ **context: Additional context (session_id, workflow_id, etc.)
185
+ """
186
+ # Add mixin to the instance
187
+ if not hasattr(node_instance, "_event_mixin"):
188
+ node_instance._event_mixin = EventEmitterMixin()
189
+
190
+ # Add methods to the instance
191
+ node_instance.set_event_context = node_instance._event_mixin.set_event_context
192
+ node_instance.emit_node_started = node_instance._event_mixin.emit_node_started
193
+ node_instance.emit_node_completed = (
194
+ node_instance._event_mixin.emit_node_completed
195
+ )
196
+ node_instance.emit_node_failed = node_instance._event_mixin.emit_node_failed
197
+ node_instance.emit_node_progress = node_instance._event_mixin.emit_node_progress
198
+ node_instance.has_event_stream = node_instance._event_mixin.has_event_stream
199
+
200
+ # Set the event context
201
+ node_instance.set_event_context(event_stream, **context)
@@ -5,9 +5,11 @@ allowing them to discover and use MCP tools without being an LLM agent.
5
5
  """
6
6
 
7
7
  import asyncio
8
- from typing import Any
8
+ from typing import TYPE_CHECKING, Any
9
9
 
10
- from kailash.mcp import MCPClient
10
+ # Avoid circular import
11
+ if TYPE_CHECKING:
12
+ from kailash.middleware.mcp import MiddlewareMCPClient as MCPClient
11
13
 
12
14
 
13
15
  class MCPCapabilityMixin:
@@ -43,10 +45,13 @@ class MCPCapabilityMixin:
43
45
  self._mcp_client = None
44
46
 
45
47
  @property
46
- def mcp_client(self) -> MCPClient:
48
+ def mcp_client(self):
47
49
  """Get or create MCP client instance."""
48
50
  if self._mcp_client is None:
49
- self._mcp_client = MCPClient()
51
+ # Lazy import to avoid circular dependency
52
+ from kailash.middleware.mcp import MiddlewareMCPClient
53
+
54
+ self._mcp_client = MiddlewareMCPClient()
50
55
  return self._mcp_client
51
56
 
52
57
  async def discover_mcp_tools(
@@ -0,0 +1,165 @@
1
+ """
2
+ Security-related mixins for Kailash nodes.
3
+
4
+ These mixins provide security, performance, and logging capabilities
5
+ that can be mixed into any node class.
6
+ """
7
+
8
+ import logging
9
+ import time
10
+ from functools import wraps
11
+ from typing import Any, Dict, Optional
12
+
13
+
14
+ class SecurityMixin:
15
+ """
16
+ Mixin that adds security features to nodes.
17
+
18
+ Provides:
19
+ - Security context management
20
+ - Audit logging capabilities
21
+ - Access control integration
22
+ """
23
+
24
+ def __init__(self, *args, **kwargs):
25
+ super().__init__(*args, **kwargs)
26
+ self._security_context = {}
27
+ self._audit_enabled = kwargs.get("audit_enabled", True)
28
+ self._log_context = {} # Initialize log context for log_with_context method
29
+
30
+ def set_security_context(self, context: Dict[str, Any]) -> None:
31
+ """Set security context for the node."""
32
+ self._security_context = context
33
+
34
+ def get_security_context(self) -> Dict[str, Any]:
35
+ """Get current security context."""
36
+ return self._security_context
37
+
38
+ def audit_log(self, action: str, details: Dict[str, Any]) -> None:
39
+ """Log an audit event."""
40
+ if self._audit_enabled:
41
+ # In a real implementation, this would integrate with AuditLogNode
42
+ print(f"[AUDIT] {action}: {details}")
43
+
44
+ def validate_and_sanitize_inputs(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
45
+ """Validate and sanitize input parameters."""
46
+ # Basic implementation - in production this would do more validation
47
+ sanitized = {}
48
+ for key, value in inputs.items():
49
+ if isinstance(value, str):
50
+ # Basic sanitization - remove leading/trailing whitespace
51
+ sanitized[key] = value.strip()
52
+ else:
53
+ sanitized[key] = value
54
+ return sanitized
55
+
56
+
57
+ class PerformanceMixin:
58
+ """
59
+ Mixin that adds performance monitoring to nodes.
60
+
61
+ Provides:
62
+ - Execution time tracking
63
+ - Performance metrics collection
64
+ - SLA monitoring
65
+ """
66
+
67
+ def __init__(self, *args, **kwargs):
68
+ super().__init__(*args, **kwargs)
69
+ self._performance_metrics = []
70
+ self._sla_target_ms = kwargs.get("sla_target_ms", 1000)
71
+
72
+ def track_performance(self, func):
73
+ """Decorator to track method performance."""
74
+
75
+ @wraps(func)
76
+ def wrapper(*args, **kwargs):
77
+ start_time = time.time()
78
+ try:
79
+ result = func(*args, **kwargs)
80
+ execution_time = (time.time() - start_time) * 1000 # Convert to ms
81
+ self._performance_metrics.append(
82
+ {
83
+ "method": func.__name__,
84
+ "execution_time_ms": execution_time,
85
+ "sla_met": execution_time <= self._sla_target_ms,
86
+ }
87
+ )
88
+ return result
89
+ except Exception as e:
90
+ execution_time = (time.time() - start_time) * 1000
91
+ self._performance_metrics.append(
92
+ {
93
+ "method": func.__name__,
94
+ "execution_time_ms": execution_time,
95
+ "error": str(e),
96
+ }
97
+ )
98
+ raise
99
+
100
+ return wrapper
101
+
102
+ def get_performance_metrics(self) -> list:
103
+ """Get collected performance metrics."""
104
+ return self._performance_metrics
105
+
106
+
107
+ class LoggingMixin:
108
+ """
109
+ Mixin that adds enhanced logging capabilities to nodes.
110
+
111
+ Provides:
112
+ - Structured logging
113
+ - Context-aware logging
114
+ - Log level management
115
+ """
116
+
117
+ def __init__(self, *args, **kwargs):
118
+ super().__init__(*args, **kwargs)
119
+ self.logger = logging.getLogger(self.__class__.__name__)
120
+ self._log_context = {}
121
+
122
+ def set_log_context(self, **context):
123
+ """Set logging context."""
124
+ self._log_context.update(context)
125
+
126
+ def log_info(self, message: str, **extra):
127
+ """Log info message with context."""
128
+ self.logger.info(message, extra={**self._log_context, **extra})
129
+
130
+ def log_error(self, message: str, error: Optional[Exception] = None, **extra):
131
+ """Log error message with context."""
132
+ log_data = {**self._log_context, **extra}
133
+ if error:
134
+ log_data["error_type"] = type(error).__name__
135
+ log_data["error_message"] = str(error)
136
+ self.logger.error(message, extra=log_data)
137
+
138
+ def log_warning(self, message: str, **extra):
139
+ """Log warning message with context."""
140
+ self.logger.warning(message, extra={**self._log_context, **extra})
141
+
142
+ def log_error_with_traceback(
143
+ self, error: Exception, operation: str = "unknown"
144
+ ) -> None:
145
+ """Log an error with full traceback information."""
146
+ import traceback
147
+
148
+ self.log_error(
149
+ f"Operation failed: {operation}",
150
+ error=error,
151
+ traceback=traceback.format_exc(),
152
+ )
153
+
154
+ def log_node_execution(self, operation: str, **context) -> None:
155
+ """Log node execution information."""
156
+ self.log_info(f"Node operation: {operation}", **context)
157
+
158
+ def log_with_context(self, level: str, message: str, **context) -> None:
159
+ """Log a message with additional context."""
160
+ full_context = {**self._log_context, **context}
161
+ context_str = " | ".join(f"{k}={v}" for k, v in full_context.items())
162
+ full_message = f"{message} | {context_str}"
163
+
164
+ log_func = getattr(self.logger, level.lower())
165
+ log_func(full_message)
@@ -0,0 +1,7 @@
1
+ """Monitoring and performance nodes for the Kailash SDK."""
2
+
3
+ from .performance_benchmark import PerformanceBenchmarkNode
4
+
5
+ __all__ = [
6
+ "PerformanceBenchmarkNode",
7
+ ]