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.
- kailash/__init__.py +33 -1
- kailash/access_control/__init__.py +129 -0
- kailash/access_control/managers.py +461 -0
- kailash/access_control/rule_evaluators.py +467 -0
- kailash/access_control_abac.py +825 -0
- kailash/config/__init__.py +27 -0
- kailash/config/database_config.py +359 -0
- kailash/database/__init__.py +28 -0
- kailash/database/execution_pipeline.py +499 -0
- kailash/middleware/__init__.py +306 -0
- kailash/middleware/auth/__init__.py +33 -0
- kailash/middleware/auth/access_control.py +436 -0
- kailash/middleware/auth/auth_manager.py +422 -0
- kailash/middleware/auth/jwt_auth.py +477 -0
- kailash/middleware/auth/kailash_jwt_auth.py +616 -0
- kailash/middleware/communication/__init__.py +37 -0
- kailash/middleware/communication/ai_chat.py +989 -0
- kailash/middleware/communication/api_gateway.py +802 -0
- kailash/middleware/communication/events.py +470 -0
- kailash/middleware/communication/realtime.py +710 -0
- kailash/middleware/core/__init__.py +21 -0
- kailash/middleware/core/agent_ui.py +890 -0
- kailash/middleware/core/schema.py +643 -0
- kailash/middleware/core/workflows.py +396 -0
- kailash/middleware/database/__init__.py +63 -0
- kailash/middleware/database/base.py +113 -0
- kailash/middleware/database/base_models.py +525 -0
- kailash/middleware/database/enums.py +106 -0
- kailash/middleware/database/migrations.py +12 -0
- kailash/{api/database.py → middleware/database/models.py} +183 -291
- kailash/middleware/database/repositories.py +685 -0
- kailash/middleware/database/session_manager.py +19 -0
- kailash/middleware/mcp/__init__.py +38 -0
- kailash/middleware/mcp/client_integration.py +585 -0
- kailash/middleware/mcp/enhanced_server.py +576 -0
- kailash/nodes/__init__.py +25 -3
- kailash/nodes/admin/__init__.py +35 -0
- kailash/nodes/admin/audit_log.py +794 -0
- kailash/nodes/admin/permission_check.py +864 -0
- kailash/nodes/admin/role_management.py +823 -0
- kailash/nodes/admin/security_event.py +1519 -0
- kailash/nodes/admin/user_management.py +944 -0
- kailash/nodes/ai/a2a.py +24 -7
- kailash/nodes/ai/ai_providers.py +1 -0
- kailash/nodes/ai/embedding_generator.py +11 -11
- kailash/nodes/ai/intelligent_agent_orchestrator.py +99 -11
- kailash/nodes/ai/llm_agent.py +407 -2
- kailash/nodes/ai/self_organizing.py +85 -10
- kailash/nodes/api/auth.py +287 -6
- kailash/nodes/api/rest.py +151 -0
- kailash/nodes/auth/__init__.py +17 -0
- kailash/nodes/auth/directory_integration.py +1228 -0
- kailash/nodes/auth/enterprise_auth_provider.py +1328 -0
- kailash/nodes/auth/mfa.py +2338 -0
- kailash/nodes/auth/risk_assessment.py +872 -0
- kailash/nodes/auth/session_management.py +1093 -0
- kailash/nodes/auth/sso.py +1040 -0
- kailash/nodes/base.py +344 -13
- kailash/nodes/base_cycle_aware.py +4 -2
- kailash/nodes/base_with_acl.py +1 -1
- kailash/nodes/code/python.py +293 -12
- kailash/nodes/compliance/__init__.py +9 -0
- kailash/nodes/compliance/data_retention.py +1888 -0
- kailash/nodes/compliance/gdpr.py +2004 -0
- kailash/nodes/data/__init__.py +22 -2
- kailash/nodes/data/async_connection.py +469 -0
- kailash/nodes/data/async_sql.py +757 -0
- kailash/nodes/data/async_vector.py +598 -0
- kailash/nodes/data/readers.py +767 -0
- kailash/nodes/data/retrieval.py +360 -1
- kailash/nodes/data/sharepoint_graph.py +397 -21
- kailash/nodes/data/sql.py +94 -5
- kailash/nodes/data/streaming.py +68 -8
- kailash/nodes/data/vector_db.py +54 -4
- kailash/nodes/enterprise/__init__.py +13 -0
- kailash/nodes/enterprise/batch_processor.py +741 -0
- kailash/nodes/enterprise/data_lineage.py +497 -0
- kailash/nodes/logic/convergence.py +31 -9
- kailash/nodes/logic/operations.py +14 -3
- kailash/nodes/mixins/__init__.py +8 -0
- kailash/nodes/mixins/event_emitter.py +201 -0
- kailash/nodes/mixins/mcp.py +9 -4
- kailash/nodes/mixins/security.py +165 -0
- kailash/nodes/monitoring/__init__.py +7 -0
- kailash/nodes/monitoring/performance_benchmark.py +2497 -0
- kailash/nodes/rag/__init__.py +284 -0
- kailash/nodes/rag/advanced.py +1615 -0
- kailash/nodes/rag/agentic.py +773 -0
- kailash/nodes/rag/conversational.py +999 -0
- kailash/nodes/rag/evaluation.py +875 -0
- kailash/nodes/rag/federated.py +1188 -0
- kailash/nodes/rag/graph.py +721 -0
- kailash/nodes/rag/multimodal.py +671 -0
- kailash/nodes/rag/optimized.py +933 -0
- kailash/nodes/rag/privacy.py +1059 -0
- kailash/nodes/rag/query_processing.py +1335 -0
- kailash/nodes/rag/realtime.py +764 -0
- kailash/nodes/rag/registry.py +547 -0
- kailash/nodes/rag/router.py +837 -0
- kailash/nodes/rag/similarity.py +1854 -0
- kailash/nodes/rag/strategies.py +566 -0
- kailash/nodes/rag/workflows.py +575 -0
- kailash/nodes/security/__init__.py +19 -0
- kailash/nodes/security/abac_evaluator.py +1411 -0
- kailash/nodes/security/audit_log.py +91 -0
- kailash/nodes/security/behavior_analysis.py +1893 -0
- kailash/nodes/security/credential_manager.py +401 -0
- kailash/nodes/security/rotating_credentials.py +760 -0
- kailash/nodes/security/security_event.py +132 -0
- kailash/nodes/security/threat_detection.py +1103 -0
- kailash/nodes/testing/__init__.py +9 -0
- kailash/nodes/testing/credential_testing.py +499 -0
- kailash/nodes/transform/__init__.py +10 -2
- kailash/nodes/transform/chunkers.py +592 -1
- kailash/nodes/transform/processors.py +484 -14
- kailash/nodes/validation.py +321 -0
- kailash/runtime/access_controlled.py +1 -1
- kailash/runtime/async_local.py +41 -7
- kailash/runtime/docker.py +1 -1
- kailash/runtime/local.py +474 -55
- kailash/runtime/parallel.py +1 -1
- kailash/runtime/parallel_cyclic.py +1 -1
- kailash/runtime/testing.py +210 -2
- kailash/utils/migrations/__init__.py +25 -0
- kailash/utils/migrations/generator.py +433 -0
- kailash/utils/migrations/models.py +231 -0
- kailash/utils/migrations/runner.py +489 -0
- kailash/utils/secure_logging.py +342 -0
- kailash/workflow/__init__.py +16 -0
- kailash/workflow/cyclic_runner.py +3 -4
- kailash/workflow/graph.py +70 -2
- kailash/workflow/resilience.py +249 -0
- kailash/workflow/templates.py +726 -0
- {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/METADATA +253 -20
- kailash-0.4.0.dist-info/RECORD +223 -0
- kailash/api/__init__.py +0 -17
- kailash/api/__main__.py +0 -6
- kailash/api/studio_secure.py +0 -893
- kailash/mcp/__main__.py +0 -13
- kailash/mcp/server_new.py +0 -336
- kailash/mcp/servers/__init__.py +0 -12
- kailash-0.3.1.dist-info/RECORD +0 -136
- {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/WHEEL +0 -0
- {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/entry_points.txt +0 -0
- {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/top_level.txt +0 -0
@@ -1,17 +1,13 @@
|
|
1
1
|
"""
|
2
|
-
Database
|
2
|
+
Enhanced Database Models for Kailash Middleware
|
3
3
|
|
4
|
-
|
5
|
-
-
|
6
|
-
- Database initialization and migration support
|
7
|
-
- Repository classes for data access
|
4
|
+
Consolidates and enhances existing database models from api/database.py
|
5
|
+
with middleware-specific features and event integration.
|
8
6
|
"""
|
9
7
|
|
10
8
|
import uuid
|
11
|
-
from
|
12
|
-
from
|
13
|
-
from pathlib import Path
|
14
|
-
from typing import Any
|
9
|
+
from datetime import datetime, timezone
|
10
|
+
from typing import Any, Dict, List, Optional
|
15
11
|
|
16
12
|
from sqlalchemy import (
|
17
13
|
JSON,
|
@@ -25,16 +21,14 @@ from sqlalchemy import (
|
|
25
21
|
Text,
|
26
22
|
create_engine,
|
27
23
|
)
|
28
|
-
from sqlalchemy.
|
29
|
-
from sqlalchemy.ext.declarative import declarative_base
|
30
|
-
from sqlalchemy.orm import Session, relationship, sessionmaker
|
24
|
+
from sqlalchemy.orm import declarative_base, relationship
|
31
25
|
from sqlalchemy.sql import func
|
32
26
|
|
33
27
|
Base = declarative_base()
|
34
28
|
|
35
29
|
|
36
|
-
class
|
37
|
-
"""
|
30
|
+
class WorkflowModel(Base):
|
31
|
+
"""Enhanced workflow model with middleware integration"""
|
38
32
|
|
39
33
|
__tablename__ = "workflows"
|
40
34
|
|
@@ -45,26 +39,41 @@ class Workflow(Base):
|
|
45
39
|
definition = Column(JSON, nullable=False)
|
46
40
|
version = Column(Integer, default=1)
|
47
41
|
is_published = Column(Boolean, default=False)
|
42
|
+
|
43
|
+
# Middleware enhancements
|
44
|
+
session_id = Column(String(36), nullable=True, index=True) # Associated session
|
45
|
+
agent_ui_config = Column(JSON) # UI-specific configuration
|
46
|
+
real_time_enabled = Column(Boolean, default=True) # Enable real-time updates
|
47
|
+
|
48
|
+
# Metadata
|
48
49
|
created_by = Column(String(255))
|
49
50
|
created_at = Column(DateTime, default=func.now())
|
50
51
|
updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
|
51
52
|
|
52
53
|
# Relationships
|
53
54
|
executions = relationship(
|
54
|
-
"
|
55
|
+
"WorkflowExecutionModel",
|
56
|
+
back_populates="workflow",
|
57
|
+
cascade="all, delete-orphan",
|
55
58
|
)
|
56
59
|
versions = relationship(
|
57
|
-
"
|
60
|
+
"WorkflowVersionModel", back_populates="workflow", cascade="all, delete-orphan"
|
61
|
+
)
|
62
|
+
permissions = relationship(
|
63
|
+
"WorkflowPermissionModel",
|
64
|
+
back_populates="workflow",
|
65
|
+
cascade="all, delete-orphan",
|
58
66
|
)
|
59
67
|
|
60
68
|
__table_args__ = (
|
61
69
|
Index("idx_workflow_tenant_created", "tenant_id", "created_at"),
|
62
70
|
Index("idx_workflow_tenant_name", "tenant_id", "name"),
|
71
|
+
Index("idx_workflow_session", "session_id"),
|
63
72
|
)
|
64
73
|
|
65
74
|
|
66
|
-
class
|
67
|
-
"""
|
75
|
+
class WorkflowVersionModel(Base):
|
76
|
+
"""Enhanced workflow version with change tracking"""
|
68
77
|
|
69
78
|
__tablename__ = "workflow_versions"
|
70
79
|
|
@@ -73,19 +82,25 @@ class WorkflowVersion(Base):
|
|
73
82
|
version = Column(Integer, nullable=False)
|
74
83
|
definition = Column(JSON, nullable=False)
|
75
84
|
change_message = Column(Text)
|
85
|
+
|
86
|
+
# Middleware enhancements
|
87
|
+
diff_data = Column(JSON) # Structured diff from previous version
|
88
|
+
migration_notes = Column(Text) # Notes about breaking changes
|
89
|
+
|
90
|
+
# Metadata
|
76
91
|
created_by = Column(String(255))
|
77
92
|
created_at = Column(DateTime, default=func.now())
|
78
93
|
|
79
94
|
# Relationships
|
80
|
-
workflow = relationship("
|
95
|
+
workflow = relationship("WorkflowModel", back_populates="versions")
|
81
96
|
|
82
97
|
__table_args__ = (
|
83
98
|
Index("idx_version_workflow_version", "workflow_id", "version", unique=True),
|
84
99
|
)
|
85
100
|
|
86
101
|
|
87
|
-
class
|
88
|
-
"""
|
102
|
+
class CustomNodeModel(Base):
|
103
|
+
"""Enhanced custom node with middleware features"""
|
89
104
|
|
90
105
|
__tablename__ = "custom_nodes"
|
91
106
|
|
@@ -103,9 +118,14 @@ class CustomNode(Base):
|
|
103
118
|
outputs = Column(JSON) # Output port definitions
|
104
119
|
|
105
120
|
# Implementation
|
106
|
-
implementation_type = Column(String(50)) # 'python', 'workflow', 'api'
|
121
|
+
implementation_type = Column(String(50)) # 'python', 'workflow', 'api', 'kailash'
|
107
122
|
implementation = Column(JSON) # Implementation details
|
108
123
|
|
124
|
+
# Middleware enhancements
|
125
|
+
middleware_config = Column(JSON) # Middleware-specific configuration
|
126
|
+
real_time_capable = Column(Boolean, default=False) # Supports real-time updates
|
127
|
+
event_types = Column(JSON) # List of event types this node can emit
|
128
|
+
|
109
129
|
# Metadata
|
110
130
|
is_published = Column(Boolean, default=False)
|
111
131
|
created_by = Column(String(255))
|
@@ -118,8 +138,8 @@ class CustomNode(Base):
|
|
118
138
|
)
|
119
139
|
|
120
140
|
|
121
|
-
class
|
122
|
-
"""
|
141
|
+
class WorkflowExecutionModel(Base):
|
142
|
+
"""Enhanced execution model with real-time tracking"""
|
123
143
|
|
124
144
|
__tablename__ = "workflow_executions"
|
125
145
|
|
@@ -135,6 +155,12 @@ class WorkflowExecution(Base):
|
|
135
155
|
result = Column(JSON)
|
136
156
|
error = Column(Text)
|
137
157
|
|
158
|
+
# Middleware enhancements
|
159
|
+
session_id = Column(String(36), nullable=True, index=True) # Associated session
|
160
|
+
real_time_events = Column(JSON) # List of real-time events emitted
|
161
|
+
agent_ui_data = Column(JSON) # UI-specific execution data
|
162
|
+
execution_metrics = Column(JSON) # Performance and resource metrics
|
163
|
+
|
138
164
|
# Performance metrics
|
139
165
|
started_at = Column(DateTime)
|
140
166
|
completed_at = Column(DateTime)
|
@@ -144,17 +170,18 @@ class WorkflowExecution(Base):
|
|
144
170
|
node_executions = Column(JSON) # Detailed per-node execution data
|
145
171
|
|
146
172
|
# Relationships
|
147
|
-
workflow = relationship("
|
173
|
+
workflow = relationship("WorkflowModel", back_populates="executions")
|
148
174
|
|
149
175
|
__table_args__ = (
|
150
176
|
Index("idx_execution_tenant_started", "tenant_id", "started_at"),
|
151
177
|
Index("idx_execution_workflow_started", "workflow_id", "started_at"),
|
152
178
|
Index("idx_execution_status", "status"),
|
179
|
+
Index("idx_execution_session", "session_id"),
|
153
180
|
)
|
154
181
|
|
155
182
|
|
156
|
-
class
|
157
|
-
"""
|
183
|
+
class UserPreferencesModel(Base):
|
184
|
+
"""Enhanced user preferences with middleware features"""
|
158
185
|
|
159
186
|
__tablename__ = "user_preferences"
|
160
187
|
|
@@ -171,6 +198,11 @@ class UserPreferences(Base):
|
|
171
198
|
favorite_nodes = Column(JSON)
|
172
199
|
recent_workflows = Column(JSON)
|
173
200
|
|
201
|
+
# Middleware enhancements
|
202
|
+
real_time_preferences = Column(JSON) # Real-time update preferences
|
203
|
+
agent_ui_settings = Column(JSON) # Agent-UI specific settings
|
204
|
+
notification_settings = Column(JSON) # Event notification preferences
|
205
|
+
|
174
206
|
created_at = Column(DateTime, default=func.now())
|
175
207
|
updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
|
176
208
|
|
@@ -179,8 +211,8 @@ class UserPreferences(Base):
|
|
179
211
|
)
|
180
212
|
|
181
213
|
|
182
|
-
class
|
183
|
-
"""
|
214
|
+
class WorkflowTemplateModel(Base):
|
215
|
+
"""Enhanced workflow templates with middleware integration"""
|
184
216
|
|
185
217
|
__tablename__ = "workflow_templates"
|
186
218
|
|
@@ -195,6 +227,11 @@ class WorkflowTemplate(Base):
|
|
195
227
|
definition = Column(JSON, nullable=False)
|
196
228
|
default_parameters = Column(JSON)
|
197
229
|
|
230
|
+
# Middleware enhancements
|
231
|
+
middleware_features = Column(JSON) # Required middleware features
|
232
|
+
agent_ui_template = Column(JSON) # Agent-UI template configuration
|
233
|
+
real_time_template = Column(JSON) # Real-time update template
|
234
|
+
|
198
235
|
# Metadata
|
199
236
|
is_public = Column(Boolean, default=False)
|
200
237
|
usage_count = Column(Integer, default=0)
|
@@ -208,8 +245,8 @@ class WorkflowTemplate(Base):
|
|
208
245
|
)
|
209
246
|
|
210
247
|
|
211
|
-
class
|
212
|
-
"""
|
248
|
+
class WorkflowPermissionModel(Base):
|
249
|
+
"""Enhanced workflow permissions with middleware access control"""
|
213
250
|
|
214
251
|
__tablename__ = "workflow_permissions"
|
215
252
|
|
@@ -233,13 +270,18 @@ class WorkflowPermission(Base):
|
|
233
270
|
# Conditions (JSON object for flexibility)
|
234
271
|
conditions = Column(JSON)
|
235
272
|
|
273
|
+
# Middleware enhancements
|
274
|
+
session_restrictions = Column(JSON) # Session-based restrictions
|
275
|
+
real_time_permissions = Column(JSON) # Real-time access permissions
|
276
|
+
agent_ui_permissions = Column(JSON) # Agent-UI specific permissions
|
277
|
+
|
236
278
|
# Metadata
|
237
279
|
created_by = Column(String(255))
|
238
280
|
created_at = Column(DateTime, default=func.now())
|
239
281
|
expires_at = Column(DateTime, nullable=True)
|
240
282
|
|
241
283
|
# Relationships
|
242
|
-
workflow = relationship("
|
284
|
+
workflow = relationship("WorkflowModel", back_populates="permissions")
|
243
285
|
|
244
286
|
__table_args__ = (
|
245
287
|
Index("idx_workflow_perm_workflow", "workflow_id"),
|
@@ -248,8 +290,8 @@ class WorkflowPermission(Base):
|
|
248
290
|
)
|
249
291
|
|
250
292
|
|
251
|
-
class
|
252
|
-
"""
|
293
|
+
class NodePermissionModel(Base):
|
294
|
+
"""Enhanced node permissions with middleware features"""
|
253
295
|
|
254
296
|
__tablename__ = "node_permissions"
|
255
297
|
|
@@ -274,13 +316,17 @@ class NodePermission(Base):
|
|
274
316
|
masked_fields = Column(JSON) # Fields to mask in output
|
275
317
|
redirect_node = Column(String(255)) # Alternative node if access denied
|
276
318
|
|
319
|
+
# Middleware enhancements
|
320
|
+
real_time_masking = Column(JSON) # Real-time output masking rules
|
321
|
+
event_filtering = Column(JSON) # Event filtering rules for this node
|
322
|
+
|
277
323
|
# Metadata
|
278
324
|
created_by = Column(String(255))
|
279
325
|
created_at = Column(DateTime, default=func.now())
|
280
326
|
expires_at = Column(DateTime, nullable=True)
|
281
327
|
|
282
328
|
# Relationships
|
283
|
-
workflow = relationship("
|
329
|
+
workflow = relationship("WorkflowModel", backref="node_permissions")
|
284
330
|
|
285
331
|
__table_args__ = (
|
286
332
|
Index("idx_node_perm_workflow", "workflow_id"),
|
@@ -290,8 +336,8 @@ class NodePermission(Base):
|
|
290
336
|
)
|
291
337
|
|
292
338
|
|
293
|
-
class
|
294
|
-
"""
|
339
|
+
class AccessLogModel(Base):
|
340
|
+
"""Enhanced access log with middleware event integration"""
|
295
341
|
|
296
342
|
__tablename__ = "access_logs"
|
297
343
|
|
@@ -300,7 +346,7 @@ class AccessLog(Base):
|
|
300
346
|
user_id = Column(String(36), nullable=False, index=True)
|
301
347
|
|
302
348
|
# What was accessed?
|
303
|
-
resource_type = Column(String(50), nullable=False) # workflow, node
|
349
|
+
resource_type = Column(String(50), nullable=False) # workflow, node, session, api
|
304
350
|
resource_id = Column(String(255), nullable=False)
|
305
351
|
permission = Column(String(50), nullable=False)
|
306
352
|
|
@@ -313,17 +359,25 @@ class AccessLog(Base):
|
|
313
359
|
user_agent = Column(String(255))
|
314
360
|
session_id = Column(String(36))
|
315
361
|
|
362
|
+
# Middleware enhancements
|
363
|
+
event_id = Column(String(36)) # Associated middleware event
|
364
|
+
real_time_logged = Column(
|
365
|
+
Boolean, default=False
|
366
|
+
) # Whether logged to real-time stream
|
367
|
+
agent_ui_context = Column(JSON) # Agent-UI specific context
|
368
|
+
|
316
369
|
# Timestamp
|
317
370
|
timestamp = Column(DateTime, default=func.now(), index=True)
|
318
371
|
|
319
372
|
__table_args__ = (
|
320
373
|
Index("idx_access_log_user_time", "user_id", "timestamp"),
|
321
374
|
Index("idx_access_log_resource", "resource_type", "resource_id", "timestamp"),
|
375
|
+
Index("idx_access_log_event", "event_id"),
|
322
376
|
)
|
323
377
|
|
324
378
|
|
325
|
-
class
|
326
|
-
"""
|
379
|
+
class UserGroupModel(Base):
|
380
|
+
"""Enhanced user groups with middleware features"""
|
327
381
|
|
328
382
|
__tablename__ = "user_groups"
|
329
383
|
|
@@ -335,6 +389,11 @@ class UserGroup(Base):
|
|
335
389
|
# Group permissions (can be inherited)
|
336
390
|
permissions = Column(JSON)
|
337
391
|
|
392
|
+
# Middleware enhancements
|
393
|
+
middleware_permissions = Column(JSON) # Middleware-specific permissions
|
394
|
+
real_time_access = Column(JSON) # Real-time feature access
|
395
|
+
agent_ui_access = Column(JSON) # Agent-UI access configuration
|
396
|
+
|
338
397
|
# Metadata
|
339
398
|
created_by = Column(String(255))
|
340
399
|
created_at = Column(DateTime, default=func.now())
|
@@ -342,14 +401,14 @@ class UserGroup(Base):
|
|
342
401
|
|
343
402
|
# Relationships
|
344
403
|
members = relationship(
|
345
|
-
"
|
404
|
+
"UserGroupMemberModel", back_populates="group", cascade="all, delete-orphan"
|
346
405
|
)
|
347
406
|
|
348
407
|
__table_args__ = (Index("idx_group_tenant_name", "tenant_id", "name", unique=True),)
|
349
408
|
|
350
409
|
|
351
|
-
class
|
352
|
-
"""
|
410
|
+
class UserGroupMemberModel(Base):
|
411
|
+
"""Enhanced group membership with middleware tracking"""
|
353
412
|
|
354
413
|
__tablename__ = "user_group_members"
|
355
414
|
|
@@ -362,8 +421,11 @@ class UserGroupMember(Base):
|
|
362
421
|
joined_at = Column(DateTime, default=func.now())
|
363
422
|
added_by = Column(String(255))
|
364
423
|
|
424
|
+
# Middleware enhancements
|
425
|
+
middleware_role_overrides = Column(JSON) # Role overrides for middleware features
|
426
|
+
|
365
427
|
# Relationships
|
366
|
-
group = relationship("
|
428
|
+
group = relationship("UserGroupModel", back_populates="members")
|
367
429
|
|
368
430
|
__table_args__ = (
|
369
431
|
Index("idx_group_member", "group_id", "user_id", unique=True),
|
@@ -371,250 +433,80 @@ class UserGroupMember(Base):
|
|
371
433
|
)
|
372
434
|
|
373
435
|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
)
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
)
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
)
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
)
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
def get(self, workflow_id: str) -> Workflow | None:
|
452
|
-
"""Get a workflow by ID"""
|
453
|
-
return self.session.query(Workflow).filter_by(id=workflow_id).first()
|
454
|
-
|
455
|
-
def list(self, tenant_id: str, limit: int = 100, offset: int = 0) -> list[Workflow]:
|
456
|
-
"""List workflows for a tenant"""
|
457
|
-
return (
|
458
|
-
self.session.query(Workflow)
|
459
|
-
.filter_by(tenant_id=tenant_id)
|
460
|
-
.order_by(Workflow.created_at.desc())
|
461
|
-
.limit(limit)
|
462
|
-
.offset(offset)
|
463
|
-
.all()
|
464
|
-
)
|
465
|
-
|
466
|
-
def delete(self, workflow_id: str):
|
467
|
-
"""Delete a workflow"""
|
468
|
-
workflow = self.get(workflow_id)
|
469
|
-
if workflow:
|
470
|
-
self.session.delete(workflow)
|
471
|
-
self.session.commit()
|
472
|
-
|
473
|
-
|
474
|
-
class CustomNodeRepository:
|
475
|
-
"""Repository for custom node operations"""
|
476
|
-
|
477
|
-
def __init__(self, session: Session):
|
478
|
-
self.session = session
|
479
|
-
|
480
|
-
def create(self, tenant_id: str, node_data: dict[str, Any]) -> CustomNode:
|
481
|
-
"""Create a custom node"""
|
482
|
-
node = CustomNode(tenant_id=tenant_id, **node_data)
|
483
|
-
self.session.add(node)
|
484
|
-
self.session.commit()
|
485
|
-
return node
|
486
|
-
|
487
|
-
def update(self, node_id: str, updates: dict[str, Any]) -> CustomNode:
|
488
|
-
"""Update a custom node"""
|
489
|
-
node = self.session.query(CustomNode).filter_by(id=node_id).first()
|
490
|
-
if not node:
|
491
|
-
raise ValueError(f"Custom node {node_id} not found")
|
492
|
-
|
493
|
-
for key, value in updates.items():
|
494
|
-
if hasattr(node, key):
|
495
|
-
setattr(node, key, value)
|
496
|
-
|
497
|
-
self.session.commit()
|
498
|
-
return node
|
499
|
-
|
500
|
-
def list(self, tenant_id: str) -> list[CustomNode]:
|
501
|
-
"""List custom nodes for a tenant"""
|
502
|
-
return (
|
503
|
-
self.session.query(CustomNode)
|
504
|
-
.filter_by(tenant_id=tenant_id)
|
505
|
-
.order_by(CustomNode.category, CustomNode.name)
|
506
|
-
.all()
|
507
|
-
)
|
508
|
-
|
509
|
-
def get(self, node_id: str) -> CustomNode | None:
|
510
|
-
"""Get a custom node by ID"""
|
511
|
-
return self.session.query(CustomNode).filter_by(id=node_id).first()
|
512
|
-
|
513
|
-
def delete(self, node_id: str):
|
514
|
-
"""Delete a custom node"""
|
515
|
-
node = self.get(node_id)
|
516
|
-
if node:
|
517
|
-
self.session.delete(node)
|
518
|
-
self.session.commit()
|
519
|
-
|
520
|
-
|
521
|
-
class ExecutionRepository:
|
522
|
-
"""Repository for execution operations"""
|
523
|
-
|
524
|
-
def __init__(self, session: Session):
|
525
|
-
self.session = session
|
526
|
-
|
527
|
-
def create(
|
528
|
-
self, workflow_id: str, tenant_id: str, parameters: dict[str, Any] = None
|
529
|
-
) -> WorkflowExecution:
|
530
|
-
"""Create an execution record"""
|
531
|
-
execution = WorkflowExecution(
|
532
|
-
workflow_id=workflow_id,
|
533
|
-
tenant_id=tenant_id,
|
534
|
-
status="pending",
|
535
|
-
parameters=parameters,
|
536
|
-
started_at=datetime.now(UTC),
|
537
|
-
)
|
538
|
-
self.session.add(execution)
|
539
|
-
self.session.commit()
|
540
|
-
return execution
|
541
|
-
|
542
|
-
def update_status(
|
543
|
-
self,
|
544
|
-
execution_id: str,
|
545
|
-
status: str,
|
546
|
-
result: dict[str, Any] = None,
|
547
|
-
error: str = None,
|
548
|
-
):
|
549
|
-
"""Update execution status"""
|
550
|
-
execution = (
|
551
|
-
self.session.query(WorkflowExecution).filter_by(id=execution_id).first()
|
552
|
-
)
|
553
|
-
if not execution:
|
554
|
-
raise ValueError(f"Execution {execution_id} not found")
|
555
|
-
|
556
|
-
execution.status = status
|
557
|
-
if result is not None:
|
558
|
-
execution.result = result
|
559
|
-
if error is not None:
|
560
|
-
execution.error = error
|
561
|
-
|
562
|
-
if status in ["completed", "failed"]:
|
563
|
-
execution.completed_at = datetime.now(UTC)
|
564
|
-
if execution.started_at:
|
565
|
-
execution.execution_time_ms = int(
|
566
|
-
(execution.completed_at - execution.started_at).total_seconds()
|
567
|
-
* 1000
|
568
|
-
)
|
569
|
-
|
570
|
-
self.session.commit()
|
571
|
-
|
572
|
-
def get(self, execution_id: str) -> WorkflowExecution | None:
|
573
|
-
"""Get execution by ID"""
|
574
|
-
return self.session.query(WorkflowExecution).filter_by(id=execution_id).first()
|
575
|
-
|
576
|
-
def list_for_workflow(
|
577
|
-
self, workflow_id: str, limit: int = 50
|
578
|
-
) -> list[WorkflowExecution]:
|
579
|
-
"""List executions for a workflow"""
|
580
|
-
return (
|
581
|
-
self.session.query(WorkflowExecution)
|
582
|
-
.filter_by(workflow_id=workflow_id)
|
583
|
-
.order_by(WorkflowExecution.started_at.desc())
|
584
|
-
.limit(limit)
|
585
|
-
.all()
|
586
|
-
)
|
587
|
-
|
588
|
-
|
589
|
-
# Database initialization
|
590
|
-
def init_database(db_path: str = None) -> tuple[sessionmaker, Engine]:
|
591
|
-
"""Initialize the database"""
|
592
|
-
if db_path is None:
|
593
|
-
db_path = Path.home() / ".kailash" / "studio.db"
|
594
|
-
|
595
|
-
db_path = Path(db_path)
|
596
|
-
db_path.parent.mkdir(parents=True, exist_ok=True)
|
597
|
-
|
598
|
-
engine = create_engine(f"sqlite:///{db_path}", echo=False)
|
599
|
-
Base.metadata.create_all(engine)
|
600
|
-
|
601
|
-
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
602
|
-
|
603
|
-
return SessionLocal, engine
|
604
|
-
|
605
|
-
|
606
|
-
# Context manager for database sessions
|
607
|
-
|
608
|
-
|
609
|
-
@contextmanager
|
610
|
-
def get_db_session(SessionLocal):
|
611
|
-
"""Provide a transactional scope for database operations"""
|
612
|
-
session = SessionLocal()
|
613
|
-
try:
|
614
|
-
yield session
|
615
|
-
session.commit()
|
616
|
-
except Exception:
|
617
|
-
session.rollback()
|
618
|
-
raise
|
619
|
-
finally:
|
620
|
-
session.close()
|
436
|
+
class MiddlewareSessionModel(Base):
|
437
|
+
"""Middleware-specific session tracking"""
|
438
|
+
|
439
|
+
__tablename__ = "middleware_sessions"
|
440
|
+
|
441
|
+
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
442
|
+
tenant_id = Column(String(36), nullable=False, index=True)
|
443
|
+
user_id = Column(String(36), nullable=False, index=True)
|
444
|
+
|
445
|
+
# Session details
|
446
|
+
session_type = Column(String(50), nullable=False) # agent_ui, api, websocket, mcp
|
447
|
+
status = Column(String(20), default="active") # active, inactive, expired
|
448
|
+
|
449
|
+
# Session data
|
450
|
+
session_metadata = Column(JSON) # Session-specific metadata
|
451
|
+
preferences = Column(JSON) # User preferences for this session
|
452
|
+
context = Column(JSON) # Session context data
|
453
|
+
|
454
|
+
# Connection details
|
455
|
+
connection_id = Column(String(255)) # WebSocket/API connection ID
|
456
|
+
ip_address = Column(String(50))
|
457
|
+
user_agent = Column(String(255))
|
458
|
+
|
459
|
+
# Timestamps
|
460
|
+
created_at = Column(DateTime, default=func.now())
|
461
|
+
last_activity = Column(DateTime, default=func.now())
|
462
|
+
expires_at = Column(DateTime)
|
463
|
+
|
464
|
+
__table_args__ = (
|
465
|
+
Index("idx_session_tenant_user", "tenant_id", "user_id"),
|
466
|
+
Index("idx_session_status", "status"),
|
467
|
+
Index("idx_session_type", "session_type"),
|
468
|
+
Index("idx_session_activity", "last_activity"),
|
469
|
+
)
|
470
|
+
|
471
|
+
|
472
|
+
class MiddlewareEventModel(Base):
|
473
|
+
"""Middleware event logging for audit and replay"""
|
474
|
+
|
475
|
+
__tablename__ = "middleware_events"
|
476
|
+
|
477
|
+
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
478
|
+
tenant_id = Column(String(36), nullable=False, index=True)
|
479
|
+
|
480
|
+
# Event details
|
481
|
+
event_type = Column(String(100), nullable=False, index=True)
|
482
|
+
event_source = Column(
|
483
|
+
String(50), nullable=False
|
484
|
+
) # agent_ui, api_gateway, realtime, etc.
|
485
|
+
|
486
|
+
# Event data
|
487
|
+
data = Column(JSON, nullable=False)
|
488
|
+
context = Column(JSON) # Additional context
|
489
|
+
|
490
|
+
# Associated entities
|
491
|
+
session_id = Column(String(36), nullable=True, index=True)
|
492
|
+
user_id = Column(String(36), nullable=True, index=True)
|
493
|
+
workflow_id = Column(String(36), nullable=True, index=True)
|
494
|
+
execution_id = Column(String(36), nullable=True, index=True)
|
495
|
+
|
496
|
+
# Event metadata
|
497
|
+
correlation_id = Column(String(36)) # For tracing related events
|
498
|
+
sequence_number = Column(Integer) # For ordering within correlation
|
499
|
+
|
500
|
+
# Processing status
|
501
|
+
processed = Column(Boolean, default=False)
|
502
|
+
processed_at = Column(DateTime)
|
503
|
+
error_message = Column(Text)
|
504
|
+
|
505
|
+
# Timestamp
|
506
|
+
timestamp = Column(DateTime, default=func.now(), index=True)
|
507
|
+
|
508
|
+
__table_args__ = (
|
509
|
+
Index("idx_event_type_time", "event_type", "timestamp"),
|
510
|
+
Index("idx_event_correlation", "correlation_id", "sequence_number"),
|
511
|
+
Index("idx_event_processed", "processed"),
|
512
|
+
)
|