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,297 @@
1
+ """Persistence helpers for memory modules."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from pathlib import Path
7
+ from typing import Any, Dict, Iterable, List, Optional
8
+ import json
9
+ import logging
10
+ import sqlite3
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ @dataclass
16
+ class MemoryPersistenceConfig:
17
+ """Configuration for file-based memory persistence."""
18
+
19
+ base_dir: Path
20
+ enabled: bool = False
21
+ backend: str = "json" # "json" or "sqlite"
22
+ sqlite_path: Optional[Path] = None
23
+
24
+ def resolve(self, filename: str) -> Path:
25
+ """Resolve a filename within the persistence directory."""
26
+ return self.base_dir / filename
27
+
28
+ def resolve_sqlite_path(self) -> Path:
29
+ """Resolve SQLite database path."""
30
+ if self.sqlite_path:
31
+ return self.sqlite_path
32
+ return self.base_dir / "memory.db"
33
+
34
+
35
+ class JsonMemoryStore:
36
+ """Simple JSON file store for memory objects."""
37
+
38
+ def __init__(self, config: MemoryPersistenceConfig) -> None:
39
+ self.config = config
40
+
41
+ def _ensure_dir(self) -> None:
42
+ if not self.config.enabled:
43
+ return
44
+ self.config.base_dir.mkdir(parents=True, exist_ok=True)
45
+
46
+ def load_list(self, filename: str) -> List[Dict[str, Any]]:
47
+ """Load a list of dictionaries from disk."""
48
+ if not self.config.enabled:
49
+ return []
50
+
51
+ path = self.config.resolve(filename)
52
+ if not path.exists():
53
+ return []
54
+
55
+ try:
56
+ with path.open("r", encoding="utf-8") as file:
57
+ data = json.load(file)
58
+ if isinstance(data, list):
59
+ return data
60
+ logger.warning("Unexpected data format in %s", path)
61
+ return []
62
+ except Exception as exc:
63
+ logger.error("Failed to load %s: %s", path, exc)
64
+ return []
65
+
66
+ def save_list(self, filename: str, items: Iterable[Dict[str, Any]]) -> None:
67
+ """Save a list of dictionaries to disk."""
68
+ if not self.config.enabled:
69
+ return
70
+
71
+ self._ensure_dir()
72
+ path = self.config.resolve(filename)
73
+ try:
74
+ with path.open("w", encoding="utf-8") as file:
75
+ json.dump(list(items), file, indent=2, default=str)
76
+ except Exception as exc:
77
+ logger.error("Failed to save %s: %s", path, exc)
78
+
79
+ def load_mapping(self, filename: str) -> Dict[str, Any]:
80
+ """Load a mapping from disk."""
81
+ if not self.config.enabled:
82
+ return {}
83
+
84
+ path = self.config.resolve(filename)
85
+ if not path.exists():
86
+ return {}
87
+
88
+ try:
89
+ with path.open("r", encoding="utf-8") as file:
90
+ data = json.load(file)
91
+ if isinstance(data, dict):
92
+ return data
93
+ logger.warning("Unexpected data format in %s", path)
94
+ return {}
95
+ except Exception as exc:
96
+ logger.error("Failed to load %s: %s", path, exc)
97
+ return {}
98
+
99
+ def save_mapping(self, filename: str, data: Dict[str, Any]) -> None:
100
+ """Save a mapping to disk."""
101
+ if not self.config.enabled:
102
+ return
103
+
104
+ self._ensure_dir()
105
+ path = self.config.resolve(filename)
106
+ try:
107
+ with path.open("w", encoding="utf-8") as file:
108
+ json.dump(data, file, indent=2, default=str)
109
+ except Exception as exc:
110
+ logger.error("Failed to save %s: %s", path, exc)
111
+
112
+
113
+ class SqliteMemoryStore:
114
+ """SQLite-backed key/value store for memory persistence."""
115
+
116
+ def __init__(self, config: MemoryPersistenceConfig) -> None:
117
+ self.config = config
118
+ self._initialized = False
119
+
120
+ def _ensure_db(self) -> None:
121
+ if not self.config.enabled:
122
+ return
123
+ if self._initialized:
124
+ return
125
+ self.config.base_dir.mkdir(parents=True, exist_ok=True)
126
+ db_path = self.config.resolve_sqlite_path()
127
+ conn = sqlite3.connect(db_path)
128
+ try:
129
+ cursor = conn.cursor()
130
+ cursor.execute(
131
+ """
132
+ CREATE TABLE IF NOT EXISTS memory_blobs (
133
+ key TEXT PRIMARY KEY,
134
+ payload TEXT NOT NULL
135
+ )
136
+ """
137
+ )
138
+ cursor.execute(
139
+ """
140
+ CREATE TABLE IF NOT EXISTS long_term_metadata (
141
+ memory_id TEXT PRIMARY KEY,
142
+ memory_type TEXT,
143
+ importance REAL,
144
+ timestamp TEXT,
145
+ tags TEXT,
146
+ metadata TEXT
147
+ )
148
+ """
149
+ )
150
+ conn.commit()
151
+ self._initialized = True
152
+ finally:
153
+ conn.close()
154
+
155
+ def _get_connection(self) -> sqlite3.Connection:
156
+ self._ensure_db()
157
+ return sqlite3.connect(self.config.resolve_sqlite_path())
158
+
159
+ def load_list(self, filename: str) -> List[Dict[str, Any]]:
160
+ if not self.config.enabled:
161
+ return []
162
+
163
+ self._ensure_db()
164
+ conn = self._get_connection()
165
+ try:
166
+ cursor = conn.cursor()
167
+ cursor.execute("SELECT payload FROM memory_blobs WHERE key = ?", (filename,))
168
+ row = cursor.fetchone()
169
+ if not row:
170
+ return []
171
+ data = json.loads(row[0])
172
+ return data if isinstance(data, list) else []
173
+ except Exception as exc:
174
+ logger.error("Failed to load %s from sqlite: %s", filename, exc)
175
+ return []
176
+ finally:
177
+ conn.close()
178
+
179
+ def save_list(self, filename: str, items: Iterable[Dict[str, Any]]) -> None:
180
+ if not self.config.enabled:
181
+ return
182
+
183
+ self._ensure_db()
184
+ conn = self._get_connection()
185
+ try:
186
+ payload = json.dumps(list(items), default=str)
187
+ cursor = conn.cursor()
188
+ cursor.execute(
189
+ "INSERT OR REPLACE INTO memory_blobs (key, payload) VALUES (?, ?)",
190
+ (filename, payload),
191
+ )
192
+ conn.commit()
193
+ except Exception as exc:
194
+ logger.error("Failed to save %s to sqlite: %s", filename, exc)
195
+ finally:
196
+ conn.close()
197
+
198
+ def load_mapping(self, filename: str) -> Dict[str, Any]:
199
+ if not self.config.enabled:
200
+ return {}
201
+
202
+ self._ensure_db()
203
+ conn = self._get_connection()
204
+ try:
205
+ cursor = conn.cursor()
206
+ cursor.execute("SELECT payload FROM memory_blobs WHERE key = ?", (filename,))
207
+ row = cursor.fetchone()
208
+ if not row:
209
+ return {}
210
+ data = json.loads(row[0])
211
+ return data if isinstance(data, dict) else {}
212
+ except Exception as exc:
213
+ logger.error("Failed to load %s from sqlite: %s", filename, exc)
214
+ return {}
215
+ finally:
216
+ conn.close()
217
+
218
+ def save_mapping(self, filename: str, data: Dict[str, Any]) -> None:
219
+ if not self.config.enabled:
220
+ return
221
+
222
+ self._ensure_db()
223
+ conn = self._get_connection()
224
+ try:
225
+ payload = json.dumps(data, default=str)
226
+ cursor = conn.cursor()
227
+ cursor.execute(
228
+ "INSERT OR REPLACE INTO memory_blobs (key, payload) VALUES (?, ?)",
229
+ (filename, payload),
230
+ )
231
+ conn.commit()
232
+ except Exception as exc:
233
+ logger.error("Failed to save %s to sqlite: %s", filename, exc)
234
+ finally:
235
+ conn.close()
236
+
237
+ def store_long_term_metadata(
238
+ self,
239
+ memory_id: str,
240
+ memory_type: str,
241
+ importance: float,
242
+ timestamp: str,
243
+ tags: List[str],
244
+ metadata: Dict[str, Any],
245
+ ) -> None:
246
+ if not self.config.enabled:
247
+ return
248
+
249
+ self._ensure_db()
250
+ conn = self._get_connection()
251
+ try:
252
+ cursor = conn.cursor()
253
+ cursor.execute(
254
+ """
255
+ INSERT OR REPLACE INTO long_term_metadata
256
+ (memory_id, memory_type, importance, timestamp, tags, metadata)
257
+ VALUES (?, ?, ?, ?, ?, ?)
258
+ """,
259
+ (
260
+ memory_id,
261
+ memory_type,
262
+ importance,
263
+ timestamp,
264
+ ",".join(tags),
265
+ json.dumps(metadata, default=str),
266
+ ),
267
+ )
268
+ conn.commit()
269
+ except Exception as exc:
270
+ logger.error("Failed to store long-term metadata: %s", exc)
271
+ finally:
272
+ conn.close()
273
+
274
+ def delete_long_term_metadata(self, memory_id: str) -> None:
275
+ if not self.config.enabled:
276
+ return
277
+
278
+ self._ensure_db()
279
+ conn = self._get_connection()
280
+ try:
281
+ cursor = conn.cursor()
282
+ cursor.execute(
283
+ "DELETE FROM long_term_metadata WHERE memory_id = ?",
284
+ (memory_id,),
285
+ )
286
+ conn.commit()
287
+ except Exception as exc:
288
+ logger.error("Failed to delete long-term metadata: %s", exc)
289
+ finally:
290
+ conn.close()
291
+
292
+
293
+ def create_memory_store(config: MemoryPersistenceConfig) -> JsonMemoryStore | SqliteMemoryStore:
294
+ """Factory for memory stores based on config backend."""
295
+ if config.backend == "sqlite":
296
+ return SqliteMemoryStore(config)
297
+ return JsonMemoryStore(config)