kailash 0.4.2__py3-none-any.whl → 0.6.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 (64) hide show
  1. kailash/__init__.py +1 -1
  2. kailash/client/__init__.py +12 -0
  3. kailash/client/enhanced_client.py +306 -0
  4. kailash/core/actors/__init__.py +16 -0
  5. kailash/core/actors/connection_actor.py +566 -0
  6. kailash/core/actors/supervisor.py +364 -0
  7. kailash/edge/__init__.py +16 -0
  8. kailash/edge/compliance.py +834 -0
  9. kailash/edge/discovery.py +659 -0
  10. kailash/edge/location.py +582 -0
  11. kailash/gateway/__init__.py +33 -0
  12. kailash/gateway/api.py +289 -0
  13. kailash/gateway/enhanced_gateway.py +357 -0
  14. kailash/gateway/resource_resolver.py +217 -0
  15. kailash/gateway/security.py +227 -0
  16. kailash/middleware/auth/models.py +2 -2
  17. kailash/middleware/database/base_models.py +1 -7
  18. kailash/middleware/database/repositories.py +3 -1
  19. kailash/middleware/gateway/__init__.py +22 -0
  20. kailash/middleware/gateway/checkpoint_manager.py +398 -0
  21. kailash/middleware/gateway/deduplicator.py +382 -0
  22. kailash/middleware/gateway/durable_gateway.py +417 -0
  23. kailash/middleware/gateway/durable_request.py +498 -0
  24. kailash/middleware/gateway/event_store.py +459 -0
  25. kailash/nodes/admin/audit_log.py +364 -6
  26. kailash/nodes/admin/permission_check.py +817 -33
  27. kailash/nodes/admin/role_management.py +1242 -108
  28. kailash/nodes/admin/schema_manager.py +438 -0
  29. kailash/nodes/admin/user_management.py +1209 -681
  30. kailash/nodes/api/http.py +95 -71
  31. kailash/nodes/base.py +281 -164
  32. kailash/nodes/base_async.py +30 -31
  33. kailash/nodes/code/__init__.py +8 -1
  34. kailash/nodes/code/async_python.py +1035 -0
  35. kailash/nodes/code/python.py +1 -0
  36. kailash/nodes/data/async_sql.py +12 -25
  37. kailash/nodes/data/sql.py +20 -11
  38. kailash/nodes/data/workflow_connection_pool.py +643 -0
  39. kailash/nodes/rag/__init__.py +1 -4
  40. kailash/resources/__init__.py +40 -0
  41. kailash/resources/factory.py +533 -0
  42. kailash/resources/health.py +319 -0
  43. kailash/resources/reference.py +288 -0
  44. kailash/resources/registry.py +392 -0
  45. kailash/runtime/async_local.py +711 -302
  46. kailash/testing/__init__.py +34 -0
  47. kailash/testing/async_test_case.py +353 -0
  48. kailash/testing/async_utils.py +345 -0
  49. kailash/testing/fixtures.py +458 -0
  50. kailash/testing/mock_registry.py +495 -0
  51. kailash/utils/resource_manager.py +420 -0
  52. kailash/workflow/__init__.py +8 -0
  53. kailash/workflow/async_builder.py +621 -0
  54. kailash/workflow/async_patterns.py +766 -0
  55. kailash/workflow/builder.py +93 -10
  56. kailash/workflow/cyclic_runner.py +111 -41
  57. kailash/workflow/graph.py +7 -2
  58. kailash/workflow/resilience.py +11 -1
  59. {kailash-0.4.2.dist-info → kailash-0.6.0.dist-info}/METADATA +12 -7
  60. {kailash-0.4.2.dist-info → kailash-0.6.0.dist-info}/RECORD +64 -28
  61. {kailash-0.4.2.dist-info → kailash-0.6.0.dist-info}/WHEEL +0 -0
  62. {kailash-0.4.2.dist-info → kailash-0.6.0.dist-info}/entry_points.txt +0 -0
  63. {kailash-0.4.2.dist-info → kailash-0.6.0.dist-info}/licenses/LICENSE +0 -0
  64. {kailash-0.4.2.dist-info → kailash-0.6.0.dist-info}/top_level.txt +0 -0
kailash/__init__.py CHANGED
@@ -33,7 +33,7 @@ except ImportError:
33
33
  # For backward compatibility
34
34
  WorkflowGraph = Workflow
35
35
 
36
- __version__ = "0.4.2"
36
+ __version__ = "0.6.0"
37
37
 
38
38
  __all__ = [
39
39
  # Core workflow components
@@ -0,0 +1,12 @@
1
+ """Enhanced client SDK for Kailash Gateway.
2
+
3
+ This module provides Python client for interacting with the Enhanced Gateway API.
4
+ """
5
+
6
+ from .enhanced_client import KailashClient, SyncKailashClient, WorkflowResult
7
+
8
+ __all__ = [
9
+ "KailashClient",
10
+ "SyncKailashClient",
11
+ "WorkflowResult",
12
+ ]
@@ -0,0 +1,306 @@
1
+ """Enhanced client for interacting with Kailash gateway.
2
+
3
+ This module provides async and sync clients for the Enhanced Gateway API
4
+ with support for resource references and convenient helper methods.
5
+ """
6
+
7
+ import asyncio
8
+ import json
9
+ import logging
10
+ from dataclasses import dataclass
11
+ from typing import Any, Dict, List, Optional, Union
12
+
13
+ import aiohttp
14
+
15
+ from ..gateway.resource_resolver import ResourceReference
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ @dataclass
21
+ class WorkflowResult:
22
+ """Result from workflow execution."""
23
+
24
+ request_id: str
25
+ workflow_id: str
26
+ status: str
27
+ result: Optional[Any] = None
28
+ error: Optional[str] = None
29
+ execution_time: Optional[float] = None
30
+
31
+ @property
32
+ def is_success(self) -> bool:
33
+ return self.status == "completed"
34
+
35
+ @property
36
+ def is_failed(self) -> bool:
37
+ return self.status == "failed"
38
+
39
+ @property
40
+ def is_running(self) -> bool:
41
+ return self.status in ["pending", "running"]
42
+
43
+
44
+ class KailashClient:
45
+ """Enhanced client for interacting with Kailash gateway."""
46
+
47
+ def __init__(self, base_url: str, api_key: Optional[str] = None, timeout: int = 30):
48
+ self.base_url = base_url.rstrip("/")
49
+ self.api_key = api_key
50
+ self.timeout = timeout
51
+ self._session: Optional[aiohttp.ClientSession] = None
52
+
53
+ async def __aenter__(self):
54
+ """Async context manager entry."""
55
+ await self._ensure_session()
56
+ return self
57
+
58
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
59
+ """Async context manager exit."""
60
+ await self.close()
61
+
62
+ async def _ensure_session(self):
63
+ """Ensure HTTP session exists."""
64
+ if not self._session:
65
+ headers = {}
66
+ if self.api_key:
67
+ headers["Authorization"] = f"Bearer {self.api_key}"
68
+
69
+ timeout = aiohttp.ClientTimeout(total=self.timeout)
70
+ self._session = aiohttp.ClientSession(headers=headers, timeout=timeout)
71
+
72
+ async def close(self):
73
+ """Close HTTP session."""
74
+ if self._session:
75
+ await self._session.close()
76
+ self._session = None
77
+
78
+ async def execute_workflow(
79
+ self,
80
+ workflow_id: str,
81
+ inputs: Dict[str, Any],
82
+ resources: Optional[Dict[str, Any]] = None,
83
+ context: Optional[Dict[str, Any]] = None,
84
+ wait: bool = True,
85
+ poll_interval: float = 1.0,
86
+ max_wait: float = 300.0,
87
+ ) -> WorkflowResult:
88
+ """Execute workflow with resource support."""
89
+ await self._ensure_session()
90
+
91
+ # Prepare request
92
+ request_data = {
93
+ "inputs": inputs,
94
+ "resources": resources or {},
95
+ "context": context or {},
96
+ }
97
+
98
+ # Execute workflow
99
+ async with self._session.post(
100
+ f"{self.base_url}/api/v1/workflows/{workflow_id}/execute", json=request_data
101
+ ) as response:
102
+ response.raise_for_status()
103
+ result_data = await response.json()
104
+
105
+ result = WorkflowResult(**result_data)
106
+
107
+ # Wait for completion if requested
108
+ if wait and result.is_running:
109
+ result = await self.wait_for_completion(
110
+ workflow_id,
111
+ result.request_id,
112
+ poll_interval=poll_interval,
113
+ max_wait=max_wait,
114
+ )
115
+
116
+ return result
117
+
118
+ async def wait_for_completion(
119
+ self,
120
+ workflow_id: str,
121
+ request_id: str,
122
+ poll_interval: float = 1.0,
123
+ max_wait: float = 300.0,
124
+ ) -> WorkflowResult:
125
+ """Wait for workflow completion."""
126
+ await self._ensure_session()
127
+
128
+ elapsed = 0.0
129
+ while elapsed < max_wait:
130
+ # Get status
131
+ result = await self.get_workflow_status(workflow_id, request_id)
132
+
133
+ if not result.is_running:
134
+ return result
135
+
136
+ # Wait before next poll
137
+ await asyncio.sleep(poll_interval)
138
+ elapsed += poll_interval
139
+
140
+ # Timeout
141
+ raise TimeoutError(f"Workflow did not complete within {max_wait} seconds")
142
+
143
+ async def get_workflow_status(
144
+ self, workflow_id: str, request_id: str
145
+ ) -> WorkflowResult:
146
+ """Get workflow execution status."""
147
+ await self._ensure_session()
148
+
149
+ async with self._session.get(
150
+ f"{self.base_url}/api/v1/workflows/{workflow_id}/status/{request_id}"
151
+ ) as response:
152
+ response.raise_for_status()
153
+ result_data = await response.json()
154
+
155
+ return WorkflowResult(**result_data)
156
+
157
+ async def list_workflows(self) -> Dict[str, Any]:
158
+ """List available workflows."""
159
+ await self._ensure_session()
160
+
161
+ async with self._session.get(f"{self.base_url}/api/v1/workflows") as response:
162
+ response.raise_for_status()
163
+ return await response.json()
164
+
165
+ async def get_workflow_details(self, workflow_id: str) -> Dict[str, Any]:
166
+ """Get details of a specific workflow."""
167
+ await self._ensure_session()
168
+
169
+ async with self._session.get(
170
+ f"{self.base_url}/api/v1/workflows/{workflow_id}"
171
+ ) as response:
172
+ response.raise_for_status()
173
+ return await response.json()
174
+
175
+ async def health_check(self) -> Dict[str, Any]:
176
+ """Check gateway health."""
177
+ await self._ensure_session()
178
+
179
+ async with self._session.get(f"{self.base_url}/api/v1/health") as response:
180
+ response.raise_for_status()
181
+ return await response.json()
182
+
183
+ async def list_resources(self) -> List[str]:
184
+ """List available resources."""
185
+ await self._ensure_session()
186
+
187
+ async with self._session.get(f"{self.base_url}/api/v1/resources") as response:
188
+ response.raise_for_status()
189
+ return await response.json()
190
+
191
+ # Resource reference helpers
192
+ def ref(self, resource_name: str) -> str:
193
+ """Create reference to registered resource."""
194
+ return f"@{resource_name}"
195
+
196
+ def database(
197
+ self,
198
+ host: str,
199
+ database: str,
200
+ port: int = 5432,
201
+ credentials_ref: Optional[str] = None,
202
+ **kwargs,
203
+ ) -> Dict[str, Any]:
204
+ """Create database resource reference."""
205
+ config = {"host": host, "port": port, "database": database, **kwargs}
206
+
207
+ return {
208
+ "type": "database",
209
+ "config": config,
210
+ "credentials_ref": credentials_ref,
211
+ }
212
+
213
+ def http_client(
214
+ self,
215
+ base_url: Optional[str] = None,
216
+ headers: Optional[Dict[str, str]] = None,
217
+ credentials_ref: Optional[str] = None,
218
+ **kwargs,
219
+ ) -> Dict[str, Any]:
220
+ """Create HTTP client resource reference."""
221
+ config = {**kwargs}
222
+ if base_url:
223
+ config["base_url"] = base_url
224
+ if headers:
225
+ config["headers"] = headers
226
+
227
+ return {
228
+ "type": "http_client",
229
+ "config": config,
230
+ "credentials_ref": credentials_ref,
231
+ }
232
+
233
+ def cache(
234
+ self,
235
+ host: str = "localhost",
236
+ port: int = 6379,
237
+ credentials_ref: Optional[str] = None,
238
+ **kwargs,
239
+ ) -> Dict[str, Any]:
240
+ """Create cache resource reference."""
241
+ config = {"host": host, "port": port, **kwargs}
242
+
243
+ return {"type": "cache", "config": config, "credentials_ref": credentials_ref}
244
+
245
+
246
+ # Synchronous wrapper for convenience
247
+ class SyncKailashClient:
248
+ """Synchronous wrapper for KailashClient."""
249
+
250
+ def __init__(self, base_url: str, api_key: Optional[str] = None):
251
+ self.async_client = KailashClient(base_url, api_key)
252
+
253
+ def execute_workflow(
254
+ self, workflow_id: str, inputs: Dict[str, Any], **kwargs
255
+ ) -> WorkflowResult:
256
+ """Execute workflow synchronously."""
257
+ loop = asyncio.new_event_loop()
258
+ asyncio.set_event_loop(loop)
259
+ try:
260
+ return loop.run_until_complete(
261
+ self.async_client.execute_workflow(workflow_id, inputs, **kwargs)
262
+ )
263
+ finally:
264
+ loop.close()
265
+
266
+ def list_workflows(self) -> Dict[str, Any]:
267
+ """List workflows synchronously."""
268
+ loop = asyncio.new_event_loop()
269
+ asyncio.set_event_loop(loop)
270
+ try:
271
+ return loop.run_until_complete(self.async_client.list_workflows())
272
+ finally:
273
+ loop.close()
274
+
275
+ def get_workflow_details(self, workflow_id: str) -> Dict[str, Any]:
276
+ """Get workflow details synchronously."""
277
+ loop = asyncio.new_event_loop()
278
+ asyncio.set_event_loop(loop)
279
+ try:
280
+ return loop.run_until_complete(
281
+ self.async_client.get_workflow_details(workflow_id)
282
+ )
283
+ finally:
284
+ loop.close()
285
+
286
+ def health_check(self) -> Dict[str, Any]:
287
+ """Check health synchronously."""
288
+ loop = asyncio.new_event_loop()
289
+ asyncio.set_event_loop(loop)
290
+ try:
291
+ return loop.run_until_complete(self.async_client.health_check())
292
+ finally:
293
+ loop.close()
294
+
295
+ def list_resources(self) -> List[str]:
296
+ """List resources synchronously."""
297
+ loop = asyncio.new_event_loop()
298
+ asyncio.set_event_loop(loop)
299
+ try:
300
+ return loop.run_until_complete(self.async_client.list_resources())
301
+ finally:
302
+ loop.close()
303
+
304
+ # Delegate resource helpers
305
+ def __getattr__(self, name):
306
+ return getattr(self.async_client, name)
@@ -0,0 +1,16 @@
1
+ """Actor-based components for Kailash SDK.
2
+
3
+ This module provides actor-based patterns for improved fault tolerance
4
+ and isolation in distributed systems.
5
+ """
6
+
7
+ from .connection_actor import ActorConnection, ConnectionActor, ConnectionState
8
+ from .supervisor import ActorSupervisor, SupervisionStrategy
9
+
10
+ __all__ = [
11
+ "ActorConnection",
12
+ "ConnectionState",
13
+ "ConnectionActor",
14
+ "ActorSupervisor",
15
+ "SupervisionStrategy",
16
+ ]