genxai-framework 0.1.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 (156) hide show
  1. cli/__init__.py +3 -0
  2. cli/commands/__init__.py +6 -0
  3. cli/commands/approval.py +85 -0
  4. cli/commands/audit.py +127 -0
  5. cli/commands/metrics.py +25 -0
  6. cli/commands/tool.py +389 -0
  7. cli/main.py +32 -0
  8. genxai/__init__.py +81 -0
  9. genxai/api/__init__.py +5 -0
  10. genxai/api/app.py +21 -0
  11. genxai/config/__init__.py +5 -0
  12. genxai/config/settings.py +37 -0
  13. genxai/connectors/__init__.py +19 -0
  14. genxai/connectors/base.py +122 -0
  15. genxai/connectors/kafka.py +92 -0
  16. genxai/connectors/postgres_cdc.py +95 -0
  17. genxai/connectors/registry.py +44 -0
  18. genxai/connectors/sqs.py +94 -0
  19. genxai/connectors/webhook.py +73 -0
  20. genxai/core/__init__.py +37 -0
  21. genxai/core/agent/__init__.py +32 -0
  22. genxai/core/agent/base.py +206 -0
  23. genxai/core/agent/config_io.py +59 -0
  24. genxai/core/agent/registry.py +98 -0
  25. genxai/core/agent/runtime.py +970 -0
  26. genxai/core/communication/__init__.py +6 -0
  27. genxai/core/communication/collaboration.py +44 -0
  28. genxai/core/communication/message_bus.py +192 -0
  29. genxai/core/communication/protocols.py +35 -0
  30. genxai/core/execution/__init__.py +22 -0
  31. genxai/core/execution/metadata.py +181 -0
  32. genxai/core/execution/queue.py +201 -0
  33. genxai/core/graph/__init__.py +30 -0
  34. genxai/core/graph/checkpoints.py +77 -0
  35. genxai/core/graph/edges.py +131 -0
  36. genxai/core/graph/engine.py +813 -0
  37. genxai/core/graph/executor.py +516 -0
  38. genxai/core/graph/nodes.py +161 -0
  39. genxai/core/graph/trigger_runner.py +40 -0
  40. genxai/core/memory/__init__.py +19 -0
  41. genxai/core/memory/base.py +72 -0
  42. genxai/core/memory/embedding.py +327 -0
  43. genxai/core/memory/episodic.py +448 -0
  44. genxai/core/memory/long_term.py +467 -0
  45. genxai/core/memory/manager.py +543 -0
  46. genxai/core/memory/persistence.py +297 -0
  47. genxai/core/memory/procedural.py +461 -0
  48. genxai/core/memory/semantic.py +526 -0
  49. genxai/core/memory/shared.py +62 -0
  50. genxai/core/memory/short_term.py +303 -0
  51. genxai/core/memory/vector_store.py +508 -0
  52. genxai/core/memory/working.py +211 -0
  53. genxai/core/state/__init__.py +6 -0
  54. genxai/core/state/manager.py +293 -0
  55. genxai/core/state/schema.py +115 -0
  56. genxai/llm/__init__.py +14 -0
  57. genxai/llm/base.py +150 -0
  58. genxai/llm/factory.py +329 -0
  59. genxai/llm/providers/__init__.py +1 -0
  60. genxai/llm/providers/anthropic.py +249 -0
  61. genxai/llm/providers/cohere.py +274 -0
  62. genxai/llm/providers/google.py +334 -0
  63. genxai/llm/providers/ollama.py +147 -0
  64. genxai/llm/providers/openai.py +257 -0
  65. genxai/llm/routing.py +83 -0
  66. genxai/observability/__init__.py +6 -0
  67. genxai/observability/logging.py +327 -0
  68. genxai/observability/metrics.py +494 -0
  69. genxai/observability/tracing.py +372 -0
  70. genxai/performance/__init__.py +39 -0
  71. genxai/performance/cache.py +256 -0
  72. genxai/performance/pooling.py +289 -0
  73. genxai/security/audit.py +304 -0
  74. genxai/security/auth.py +315 -0
  75. genxai/security/cost_control.py +528 -0
  76. genxai/security/default_policies.py +44 -0
  77. genxai/security/jwt.py +142 -0
  78. genxai/security/oauth.py +226 -0
  79. genxai/security/pii.py +366 -0
  80. genxai/security/policy_engine.py +82 -0
  81. genxai/security/rate_limit.py +341 -0
  82. genxai/security/rbac.py +247 -0
  83. genxai/security/validation.py +218 -0
  84. genxai/tools/__init__.py +21 -0
  85. genxai/tools/base.py +383 -0
  86. genxai/tools/builtin/__init__.py +131 -0
  87. genxai/tools/builtin/communication/__init__.py +15 -0
  88. genxai/tools/builtin/communication/email_sender.py +159 -0
  89. genxai/tools/builtin/communication/notification_manager.py +167 -0
  90. genxai/tools/builtin/communication/slack_notifier.py +118 -0
  91. genxai/tools/builtin/communication/sms_sender.py +118 -0
  92. genxai/tools/builtin/communication/webhook_caller.py +136 -0
  93. genxai/tools/builtin/computation/__init__.py +15 -0
  94. genxai/tools/builtin/computation/calculator.py +101 -0
  95. genxai/tools/builtin/computation/code_executor.py +183 -0
  96. genxai/tools/builtin/computation/data_validator.py +259 -0
  97. genxai/tools/builtin/computation/hash_generator.py +129 -0
  98. genxai/tools/builtin/computation/regex_matcher.py +201 -0
  99. genxai/tools/builtin/data/__init__.py +15 -0
  100. genxai/tools/builtin/data/csv_processor.py +213 -0
  101. genxai/tools/builtin/data/data_transformer.py +299 -0
  102. genxai/tools/builtin/data/json_processor.py +233 -0
  103. genxai/tools/builtin/data/text_analyzer.py +288 -0
  104. genxai/tools/builtin/data/xml_processor.py +175 -0
  105. genxai/tools/builtin/database/__init__.py +15 -0
  106. genxai/tools/builtin/database/database_inspector.py +157 -0
  107. genxai/tools/builtin/database/mongodb_query.py +196 -0
  108. genxai/tools/builtin/database/redis_cache.py +167 -0
  109. genxai/tools/builtin/database/sql_query.py +145 -0
  110. genxai/tools/builtin/database/vector_search.py +163 -0
  111. genxai/tools/builtin/file/__init__.py +17 -0
  112. genxai/tools/builtin/file/directory_scanner.py +214 -0
  113. genxai/tools/builtin/file/file_compressor.py +237 -0
  114. genxai/tools/builtin/file/file_reader.py +102 -0
  115. genxai/tools/builtin/file/file_writer.py +122 -0
  116. genxai/tools/builtin/file/image_processor.py +186 -0
  117. genxai/tools/builtin/file/pdf_parser.py +144 -0
  118. genxai/tools/builtin/test/__init__.py +15 -0
  119. genxai/tools/builtin/test/async_simulator.py +62 -0
  120. genxai/tools/builtin/test/data_transformer.py +99 -0
  121. genxai/tools/builtin/test/error_generator.py +82 -0
  122. genxai/tools/builtin/test/simple_math.py +94 -0
  123. genxai/tools/builtin/test/string_processor.py +72 -0
  124. genxai/tools/builtin/web/__init__.py +15 -0
  125. genxai/tools/builtin/web/api_caller.py +161 -0
  126. genxai/tools/builtin/web/html_parser.py +330 -0
  127. genxai/tools/builtin/web/http_client.py +187 -0
  128. genxai/tools/builtin/web/url_validator.py +162 -0
  129. genxai/tools/builtin/web/web_scraper.py +170 -0
  130. genxai/tools/custom/my_test_tool_2.py +9 -0
  131. genxai/tools/dynamic.py +105 -0
  132. genxai/tools/mcp_server.py +167 -0
  133. genxai/tools/persistence/__init__.py +6 -0
  134. genxai/tools/persistence/models.py +55 -0
  135. genxai/tools/persistence/service.py +322 -0
  136. genxai/tools/registry.py +227 -0
  137. genxai/tools/security/__init__.py +11 -0
  138. genxai/tools/security/limits.py +214 -0
  139. genxai/tools/security/policy.py +20 -0
  140. genxai/tools/security/sandbox.py +248 -0
  141. genxai/tools/templates.py +435 -0
  142. genxai/triggers/__init__.py +19 -0
  143. genxai/triggers/base.py +104 -0
  144. genxai/triggers/file_watcher.py +75 -0
  145. genxai/triggers/queue.py +68 -0
  146. genxai/triggers/registry.py +82 -0
  147. genxai/triggers/schedule.py +66 -0
  148. genxai/triggers/webhook.py +68 -0
  149. genxai/utils/__init__.py +1 -0
  150. genxai/utils/tokens.py +295 -0
  151. genxai_framework-0.1.0.dist-info/METADATA +495 -0
  152. genxai_framework-0.1.0.dist-info/RECORD +156 -0
  153. genxai_framework-0.1.0.dist-info/WHEEL +5 -0
  154. genxai_framework-0.1.0.dist-info/entry_points.txt +2 -0
  155. genxai_framework-0.1.0.dist-info/licenses/LICENSE +21 -0
  156. genxai_framework-0.1.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,315 @@
1
+ """Authentication and API key management for GenXAI."""
2
+
3
+ import secrets
4
+ import hashlib
5
+ import time
6
+ from typing import Optional, List, Dict, Any
7
+ from datetime import datetime, timedelta
8
+ from dataclasses import dataclass
9
+ import sqlite3
10
+ import os
11
+
12
+
13
+ @dataclass
14
+ class APIKey:
15
+ """API key model."""
16
+ key_id: str
17
+ user_id: str
18
+ name: str
19
+ key_hash: str
20
+ created_at: datetime
21
+ last_used: Optional[datetime] = None
22
+ expires_at: Optional[datetime] = None
23
+ is_active: bool = True
24
+
25
+
26
+ class APIKeyManager:
27
+ """Manage API keys for GenXAI services."""
28
+
29
+ def __init__(self, db_path: str = "genxai_keys.db"):
30
+ """Initialize API key manager.
31
+
32
+ Args:
33
+ db_path: Path to SQLite database
34
+ """
35
+ self.db_path = db_path
36
+ self._init_db()
37
+
38
+ def _init_db(self):
39
+ """Initialize database schema."""
40
+ conn = sqlite3.connect(self.db_path)
41
+ cursor = conn.cursor()
42
+
43
+ cursor.execute("""
44
+ CREATE TABLE IF NOT EXISTS api_keys (
45
+ key_id TEXT PRIMARY KEY,
46
+ user_id TEXT NOT NULL,
47
+ name TEXT NOT NULL,
48
+ key_hash TEXT NOT NULL,
49
+ created_at TIMESTAMP NOT NULL,
50
+ last_used TIMESTAMP,
51
+ expires_at TIMESTAMP,
52
+ is_active BOOLEAN NOT NULL DEFAULT 1
53
+ )
54
+ """)
55
+
56
+ cursor.execute("""
57
+ CREATE INDEX IF NOT EXISTS idx_user_id ON api_keys(user_id)
58
+ """)
59
+
60
+ cursor.execute("""
61
+ CREATE INDEX IF NOT EXISTS idx_key_hash ON api_keys(key_hash)
62
+ """)
63
+
64
+ conn.commit()
65
+ conn.close()
66
+
67
+ def generate_key(
68
+ self,
69
+ user_id: str,
70
+ name: str,
71
+ expires_in_days: Optional[int] = None
72
+ ) -> str:
73
+ """Generate new API key.
74
+
75
+ Args:
76
+ user_id: User ID
77
+ name: Key name/description
78
+ expires_in_days: Optional expiration in days
79
+
80
+ Returns:
81
+ Generated API key
82
+ """
83
+ # Generate random key
84
+ random_part = secrets.token_urlsafe(32)
85
+ env = os.getenv("GENXAI_ENV", "dev")
86
+ api_key = f"genxai_{env}_{random_part}"
87
+
88
+ # Hash the key for storage
89
+ key_hash = hashlib.sha256(api_key.encode()).hexdigest()
90
+
91
+ # Generate key ID
92
+ key_id = secrets.token_urlsafe(16)
93
+
94
+ # Calculate expiration
95
+ expires_at = None
96
+ if expires_in_days:
97
+ expires_at = datetime.utcnow() + timedelta(days=expires_in_days)
98
+
99
+ # Store in database
100
+ conn = sqlite3.connect(self.db_path)
101
+ cursor = conn.cursor()
102
+
103
+ cursor.execute("""
104
+ INSERT INTO api_keys (key_id, user_id, name, key_hash, created_at, expires_at)
105
+ VALUES (?, ?, ?, ?, ?, ?)
106
+ """, (key_id, user_id, name, key_hash, datetime.utcnow(), expires_at))
107
+
108
+ conn.commit()
109
+ conn.close()
110
+
111
+ return api_key
112
+
113
+ def validate_key(self, api_key: str) -> Optional[APIKey]:
114
+ """Validate API key.
115
+
116
+ Args:
117
+ api_key: API key to validate
118
+
119
+ Returns:
120
+ APIKey object if valid, None otherwise
121
+ """
122
+ # Hash the provided key
123
+ key_hash = hashlib.sha256(api_key.encode()).hexdigest()
124
+
125
+ # Look up in database
126
+ conn = sqlite3.connect(self.db_path)
127
+ cursor = conn.cursor()
128
+
129
+ cursor.execute("""
130
+ SELECT key_id, user_id, name, key_hash, created_at, last_used, expires_at, is_active
131
+ FROM api_keys
132
+ WHERE key_hash = ? AND is_active = 1
133
+ """, (key_hash,))
134
+
135
+ row = cursor.fetchone()
136
+
137
+ if not row:
138
+ conn.close()
139
+ return None
140
+
141
+ # Parse row
142
+ key_id, user_id, name, key_hash, created_at, last_used, expires_at, is_active = row
143
+
144
+ # Check expiration
145
+ if expires_at:
146
+ expires_dt = datetime.fromisoformat(expires_at)
147
+ if datetime.utcnow() > expires_dt:
148
+ conn.close()
149
+ return None
150
+
151
+ # Update last used
152
+ cursor.execute("""
153
+ UPDATE api_keys SET last_used = ? WHERE key_id = ?
154
+ """, (datetime.utcnow(), key_id))
155
+
156
+ conn.commit()
157
+ conn.close()
158
+
159
+ return APIKey(
160
+ key_id=key_id,
161
+ user_id=user_id,
162
+ name=name,
163
+ key_hash=key_hash,
164
+ created_at=datetime.fromisoformat(created_at),
165
+ last_used=datetime.fromisoformat(last_used) if last_used else None,
166
+ expires_at=datetime.fromisoformat(expires_at) if expires_at else None,
167
+ is_active=bool(is_active)
168
+ )
169
+
170
+ def revoke_key(self, key_id: str) -> bool:
171
+ """Revoke API key.
172
+
173
+ Args:
174
+ key_id: Key ID to revoke
175
+
176
+ Returns:
177
+ True if revoked, False otherwise
178
+ """
179
+ conn = sqlite3.connect(self.db_path)
180
+ cursor = conn.cursor()
181
+
182
+ cursor.execute("""
183
+ UPDATE api_keys SET is_active = 0 WHERE key_id = ?
184
+ """, (key_id,))
185
+
186
+ rows_affected = cursor.rowcount
187
+ conn.commit()
188
+ conn.close()
189
+
190
+ return rows_affected > 0
191
+
192
+ def list_keys(self, user_id: str) -> List[APIKey]:
193
+ """List all keys for user.
194
+
195
+ Args:
196
+ user_id: User ID
197
+
198
+ Returns:
199
+ List of API keys
200
+ """
201
+ conn = sqlite3.connect(self.db_path)
202
+ cursor = conn.cursor()
203
+
204
+ cursor.execute("""
205
+ SELECT key_id, user_id, name, key_hash, created_at, last_used, expires_at, is_active
206
+ FROM api_keys
207
+ WHERE user_id = ?
208
+ ORDER BY created_at DESC
209
+ """, (user_id,))
210
+
211
+ keys = []
212
+ for row in cursor.fetchall():
213
+ key_id, user_id, name, key_hash, created_at, last_used, expires_at, is_active = row
214
+ keys.append(APIKey(
215
+ key_id=key_id,
216
+ user_id=user_id,
217
+ name=name,
218
+ key_hash=key_hash,
219
+ created_at=datetime.fromisoformat(created_at),
220
+ last_used=datetime.fromisoformat(last_used) if last_used else None,
221
+ expires_at=datetime.fromisoformat(expires_at) if expires_at else None,
222
+ is_active=bool(is_active)
223
+ ))
224
+
225
+ conn.close()
226
+ return keys
227
+
228
+ def rotate_key(self, key_id: str) -> str:
229
+ """Rotate API key.
230
+
231
+ Args:
232
+ key_id: Key ID to rotate
233
+
234
+ Returns:
235
+ New API key
236
+ """
237
+ # Get existing key
238
+ conn = sqlite3.connect(self.db_path)
239
+ cursor = conn.cursor()
240
+
241
+ cursor.execute("""
242
+ SELECT user_id, name, expires_at FROM api_keys WHERE key_id = ?
243
+ """, (key_id,))
244
+
245
+ row = cursor.fetchone()
246
+ conn.close()
247
+
248
+ if not row:
249
+ raise ValueError(f"Key not found: {key_id}")
250
+
251
+ user_id, name, expires_at = row
252
+
253
+ # Revoke old key
254
+ self.revoke_key(key_id)
255
+
256
+ # Generate new key
257
+ expires_in_days = None
258
+ if expires_at:
259
+ expires_dt = datetime.fromisoformat(expires_at)
260
+ expires_in_days = (expires_dt - datetime.utcnow()).days
261
+
262
+ return self.generate_key(user_id, name, expires_in_days)
263
+
264
+
265
+ # Global API key manager
266
+ _api_key_manager = None
267
+
268
+
269
+ def get_api_key_manager() -> APIKeyManager:
270
+ """Get global API key manager.
271
+
272
+ Returns:
273
+ APIKeyManager instance
274
+ """
275
+ global _api_key_manager
276
+
277
+ if _api_key_manager is None:
278
+ db_path = os.getenv("GENXAI_API_KEY_DB", "genxai_keys.db")
279
+ _api_key_manager = APIKeyManager(db_path)
280
+
281
+ return _api_key_manager
282
+
283
+
284
+ def require_api_key(func):
285
+ """Decorator to require API key authentication.
286
+
287
+ Usage:
288
+ @require_api_key
289
+ async def my_endpoint():
290
+ pass
291
+ """
292
+ from functools import wraps
293
+
294
+ @wraps(func)
295
+ async def wrapper(*args, **kwargs):
296
+ # Get API key from request headers
297
+ # This is a placeholder - actual implementation depends on web framework
298
+ api_key = kwargs.get("api_key") or os.getenv("GENXAI_API_KEY")
299
+
300
+ if not api_key:
301
+ raise ValueError("API key required")
302
+
303
+ # Validate key
304
+ manager = get_api_key_manager()
305
+ key_obj = manager.validate_key(api_key)
306
+
307
+ if not key_obj:
308
+ raise ValueError("Invalid API key")
309
+
310
+ # Add user_id to kwargs
311
+ kwargs["user_id"] = key_obj.user_id
312
+
313
+ return await func(*args, **kwargs)
314
+
315
+ return wrapper