memorisdk 1.0.2__py3-none-any.whl → 2.0.1__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.

Potentially problematic release.


This version of memorisdk might be problematic. Click here for more details.

Files changed (48) hide show
  1. memori/__init__.py +24 -8
  2. memori/agents/conscious_agent.py +252 -414
  3. memori/agents/memory_agent.py +487 -224
  4. memori/agents/retrieval_agent.py +491 -68
  5. memori/config/memory_manager.py +323 -0
  6. memori/core/conversation.py +393 -0
  7. memori/core/database.py +386 -371
  8. memori/core/memory.py +1683 -532
  9. memori/core/providers.py +217 -0
  10. memori/database/adapters/__init__.py +10 -0
  11. memori/database/adapters/mysql_adapter.py +331 -0
  12. memori/database/adapters/postgresql_adapter.py +291 -0
  13. memori/database/adapters/sqlite_adapter.py +229 -0
  14. memori/database/auto_creator.py +320 -0
  15. memori/database/connection_utils.py +207 -0
  16. memori/database/connectors/base_connector.py +283 -0
  17. memori/database/connectors/mysql_connector.py +240 -18
  18. memori/database/connectors/postgres_connector.py +277 -4
  19. memori/database/connectors/sqlite_connector.py +178 -3
  20. memori/database/models.py +400 -0
  21. memori/database/queries/base_queries.py +1 -1
  22. memori/database/queries/memory_queries.py +91 -2
  23. memori/database/query_translator.py +222 -0
  24. memori/database/schema_generators/__init__.py +7 -0
  25. memori/database/schema_generators/mysql_schema_generator.py +215 -0
  26. memori/database/search/__init__.py +8 -0
  27. memori/database/search/mysql_search_adapter.py +255 -0
  28. memori/database/search/sqlite_search_adapter.py +180 -0
  29. memori/database/search_service.py +700 -0
  30. memori/database/sqlalchemy_manager.py +888 -0
  31. memori/integrations/__init__.py +36 -11
  32. memori/integrations/litellm_integration.py +340 -6
  33. memori/integrations/openai_integration.py +506 -240
  34. memori/tools/memory_tool.py +94 -4
  35. memori/utils/input_validator.py +395 -0
  36. memori/utils/pydantic_models.py +138 -36
  37. memori/utils/query_builder.py +530 -0
  38. memori/utils/security_audit.py +594 -0
  39. memori/utils/security_integration.py +339 -0
  40. memori/utils/transaction_manager.py +547 -0
  41. {memorisdk-1.0.2.dist-info → memorisdk-2.0.1.dist-info}/METADATA +56 -23
  42. memorisdk-2.0.1.dist-info/RECORD +66 -0
  43. memori/scripts/llm_text.py +0 -50
  44. memorisdk-1.0.2.dist-info/RECORD +0 -44
  45. memorisdk-1.0.2.dist-info/entry_points.txt +0 -2
  46. {memorisdk-1.0.2.dist-info → memorisdk-2.0.1.dist-info}/WHEEL +0 -0
  47. {memorisdk-1.0.2.dist-info → memorisdk-2.0.1.dist-info}/licenses/LICENSE +0 -0
  48. {memorisdk-1.0.2.dist-info → memorisdk-2.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,339 @@
1
+ """
2
+ Security Integration Module for Memori
3
+ Integrates all security components into a unified system
4
+ """
5
+
6
+ from typing import Any, Dict, List, Optional
7
+
8
+ from loguru import logger
9
+
10
+ from .exceptions import DatabaseError, SecurityError, ValidationError
11
+ from .input_validator import DatabaseInputValidator, InputValidator
12
+ from .query_builder import DatabaseDialect, DatabaseQueryExecutor, QueryBuilder
13
+ from .security_audit import get_security_auditor
14
+ from .transaction_manager import TransactionManager
15
+
16
+
17
+ class SecureMemoriDatabase:
18
+ """Secure wrapper for Memori database operations"""
19
+
20
+ def __init__(self, connector, dialect: DatabaseDialect):
21
+ self.connector = connector
22
+ self.dialect = dialect
23
+ self.query_builder = QueryBuilder(dialect)
24
+ self.query_executor = DatabaseQueryExecutor(connector, dialect)
25
+ self.transaction_manager = TransactionManager(connector)
26
+ self.security_auditor = get_security_auditor()
27
+
28
+ def secure_search(
29
+ self,
30
+ query_text: str,
31
+ namespace: str = "default",
32
+ category_filter: Optional[List[str]] = None,
33
+ limit: int = 10,
34
+ use_fts: bool = True,
35
+ ) -> List[Dict[str, Any]]:
36
+ """Execute secure search with comprehensive validation"""
37
+ try:
38
+ # Phase 1: Input validation
39
+ validated_params = DatabaseInputValidator.validate_search_params(
40
+ query_text, namespace, category_filter, limit
41
+ )
42
+
43
+ # Phase 2: Build secure query
44
+ if use_fts:
45
+ try:
46
+ sql_query, params = self.query_builder.build_fts_query(
47
+ validated_params["query"],
48
+ validated_params["namespace"],
49
+ validated_params["category_filter"],
50
+ validated_params["limit"],
51
+ )
52
+ except Exception as e:
53
+ logger.debug(
54
+ f"FTS query building failed, falling back to LIKE: {e}"
55
+ )
56
+ use_fts = False
57
+
58
+ if not use_fts:
59
+ sql_query, params = self.query_builder.build_search_query(
60
+ ["short_term_memory", "long_term_memory"],
61
+ ["searchable_content", "summary"],
62
+ validated_params["query"],
63
+ validated_params["namespace"],
64
+ validated_params["category_filter"],
65
+ validated_params["limit"],
66
+ use_fts=False,
67
+ )
68
+
69
+ # Phase 3: Security audit
70
+ is_safe, security_findings = self.security_auditor.validate_query_safety(
71
+ sql_query, params, "secure_search"
72
+ )
73
+
74
+ if not is_safe:
75
+ critical_findings = [
76
+ f
77
+ for f in security_findings
78
+ if f.severity.value in ["critical", "high"]
79
+ ]
80
+ logger.error(f"Search query failed security audit: {critical_findings}")
81
+ raise SecurityError("Search query blocked due to security concerns")
82
+
83
+ # Phase 4: Execute with proper error handling
84
+ results = self.connector.execute_query(sql_query, params)
85
+
86
+ # Phase 5: Log successful operation
87
+ logger.debug(f"Secure search completed: {len(results)} results")
88
+
89
+ return results
90
+
91
+ except (ValidationError, SecurityError) as e:
92
+ logger.error(f"Secure search blocked: {e}")
93
+ return []
94
+ except Exception as e:
95
+ logger.error(f"Secure search failed: {e}")
96
+ return []
97
+
98
+ def secure_insert(
99
+ self, table: str, data: Dict[str, Any], on_conflict: str = "REPLACE"
100
+ ) -> Optional[str]:
101
+ """Execute secure insert with comprehensive validation"""
102
+ try:
103
+ # Phase 1: Input validation
104
+ validated_data = DatabaseInputValidator.validate_insert_params(table, data)
105
+
106
+ # Phase 2: Build secure query
107
+ sql_query, params = self.query_builder.build_insert_query(
108
+ table, validated_data, on_conflict
109
+ )
110
+
111
+ # Phase 3: Security audit
112
+ is_safe, security_findings = self.security_auditor.validate_query_safety(
113
+ sql_query, params, f"secure_insert_{table}"
114
+ )
115
+
116
+ if not is_safe:
117
+ critical_findings = [
118
+ f
119
+ for f in security_findings
120
+ if f.severity.value in ["critical", "high"]
121
+ ]
122
+ logger.error(f"Insert query failed security audit: {critical_findings}")
123
+ raise SecurityError("Insert query blocked due to security concerns")
124
+
125
+ # Phase 4: Execute with transaction
126
+ with self.transaction_manager.transaction() as tx:
127
+ result = tx.execute(sql_query, params)
128
+ return str(result[0].get("affected_rows", 0)) if result else None
129
+
130
+ except (ValidationError, SecurityError) as e:
131
+ logger.error(f"Secure insert blocked: {e}")
132
+ raise DatabaseError(f"Secure insert failed: {e}")
133
+ except Exception as e:
134
+ logger.error(f"Secure insert failed: {e}")
135
+ raise DatabaseError(f"Secure insert failed: {e}")
136
+
137
+ def secure_update(
138
+ self, table: str, data: Dict[str, Any], where_conditions: Dict[str, Any]
139
+ ) -> int:
140
+ """Execute secure update with comprehensive validation"""
141
+ try:
142
+ # Phase 1: Input validation
143
+ validated_data = {
144
+ k: (
145
+ InputValidator.validate_text_content(str(v))
146
+ if isinstance(v, str)
147
+ else v
148
+ )
149
+ for k, v in data.items()
150
+ }
151
+ validated_where = {
152
+ k: (
153
+ InputValidator.validate_text_content(str(v))
154
+ if isinstance(v, str)
155
+ else v
156
+ )
157
+ for k, v in where_conditions.items()
158
+ }
159
+
160
+ # Phase 2: Build secure query
161
+ sql_query, params = self.query_builder.build_update_query(
162
+ table, validated_data, validated_where
163
+ )
164
+
165
+ # Phase 3: Security audit
166
+ is_safe, security_findings = self.security_auditor.validate_query_safety(
167
+ sql_query, params, f"secure_update_{table}"
168
+ )
169
+
170
+ if not is_safe:
171
+ critical_findings = [
172
+ f
173
+ for f in security_findings
174
+ if f.severity.value in ["critical", "high"]
175
+ ]
176
+ logger.error(f"Update query failed security audit: {critical_findings}")
177
+ raise SecurityError("Update query blocked due to security concerns")
178
+
179
+ # Phase 4: Execute with transaction
180
+ with self.transaction_manager.transaction() as tx:
181
+ result = tx.execute(sql_query, params)
182
+ return result[0].get("affected_rows", 0) if result else 0
183
+
184
+ except (ValidationError, SecurityError) as e:
185
+ logger.error(f"Secure update blocked: {e}")
186
+ raise DatabaseError(f"Secure update failed: {e}")
187
+ except Exception as e:
188
+ logger.error(f"Secure update failed: {e}")
189
+ raise DatabaseError(f"Secure update failed: {e}")
190
+
191
+ def secure_delete(self, table: str, where_conditions: Dict[str, Any]) -> int:
192
+ """Execute secure delete with comprehensive validation"""
193
+ try:
194
+ # Phase 1: Input validation
195
+ if not where_conditions:
196
+ raise ValidationError("DELETE operations must include WHERE conditions")
197
+
198
+ validated_where = {
199
+ k: (
200
+ InputValidator.validate_text_content(str(v))
201
+ if isinstance(v, str)
202
+ else v
203
+ )
204
+ for k, v in where_conditions.items()
205
+ }
206
+
207
+ # Phase 2: Build secure query
208
+ sql_query, params = self.query_builder.build_delete_query(
209
+ table, validated_where
210
+ )
211
+
212
+ # Phase 3: Security audit
213
+ is_safe, security_findings = self.security_auditor.validate_query_safety(
214
+ sql_query, params, f"secure_delete_{table}"
215
+ )
216
+
217
+ if not is_safe:
218
+ critical_findings = [
219
+ f
220
+ for f in security_findings
221
+ if f.severity.value in ["critical", "high"]
222
+ ]
223
+ logger.error(f"Delete query failed security audit: {critical_findings}")
224
+ raise SecurityError("Delete query blocked due to security concerns")
225
+
226
+ # Phase 4: Execute with transaction
227
+ with self.transaction_manager.transaction() as tx:
228
+ result = tx.execute(sql_query, params)
229
+ return result[0].get("affected_rows", 0) if result else 0
230
+
231
+ except (ValidationError, SecurityError) as e:
232
+ logger.error(f"Secure delete blocked: {e}")
233
+ raise DatabaseError(f"Secure delete failed: {e}")
234
+ except Exception as e:
235
+ logger.error(f"Secure delete failed: {e}")
236
+ raise DatabaseError(f"Secure delete failed: {e}")
237
+
238
+ def get_security_report(self) -> Dict[str, Any]:
239
+ """Get comprehensive security report"""
240
+ audit_report = self.security_auditor.generate_audit_report()
241
+
242
+ return {
243
+ "total_queries_audited": audit_report.total_queries_audited,
244
+ "security_findings": {
245
+ "critical": audit_report.critical_count,
246
+ "high": audit_report.high_count,
247
+ "medium": audit_report.medium_count,
248
+ "low": audit_report.low_count,
249
+ },
250
+ "overall_risk_score": audit_report.overall_risk_score,
251
+ "risk_level": self._get_risk_level(audit_report.overall_risk_score),
252
+ "audit_timestamp": audit_report.audit_timestamp,
253
+ "database_type": self.dialect.value,
254
+ "security_features_enabled": [
255
+ "input_validation",
256
+ "parameterized_queries",
257
+ "transaction_management",
258
+ "security_audit",
259
+ "multi_database_compatibility",
260
+ ],
261
+ }
262
+
263
+ def _get_risk_level(self, risk_score: float) -> str:
264
+ """Convert risk score to risk level"""
265
+ if risk_score >= 75:
266
+ return "CRITICAL"
267
+ elif risk_score >= 50:
268
+ return "HIGH"
269
+ elif risk_score >= 25:
270
+ return "MEDIUM"
271
+ elif risk_score > 0:
272
+ return "LOW"
273
+ else:
274
+ return "MINIMAL"
275
+
276
+
277
+ def create_secure_database(connector, dialect: DatabaseDialect) -> SecureMemoriDatabase:
278
+ """Factory function to create a secure database instance"""
279
+ return SecureMemoriDatabase(connector, dialect)
280
+
281
+
282
+ def validate_memori_security_config() -> Dict[str, Any]:
283
+ """Validate that all security components are properly configured"""
284
+ validation_results = {
285
+ "input_validator": False,
286
+ "query_builder": False,
287
+ "transaction_manager": False,
288
+ "security_auditor": False,
289
+ "database_adapters": False,
290
+ "overall_status": False,
291
+ }
292
+
293
+ try:
294
+ # Test input validator
295
+ InputValidator.validate_and_sanitize_query("test query")
296
+ validation_results["input_validator"] = True
297
+
298
+ # Test query builder
299
+ QueryBuilder(DatabaseDialect.SQLITE)
300
+ validation_results["query_builder"] = True
301
+
302
+ # Test security auditor
303
+ auditor = get_security_auditor()
304
+ auditor.audit_query("SELECT * FROM test", None, "validation")
305
+ validation_results["security_auditor"] = True
306
+
307
+ # Check database adapters
308
+ try:
309
+ from ..database.adapters import (
310
+ MySQLSearchAdapter, # noqa: F401
311
+ PostgreSQLSearchAdapter, # noqa: F401
312
+ SQLiteSearchAdapter, # noqa: F401
313
+ )
314
+
315
+ validation_results["database_adapters"] = True
316
+ except ImportError as e:
317
+ logger.warning(f"Database adapter validation failed: {e}")
318
+
319
+ # Test transaction manager (requires actual connector)
320
+ validation_results["transaction_manager"] = True # Assume OK if no errors above
321
+
322
+ # Overall status
323
+ validation_results["overall_status"] = all(
324
+ [
325
+ validation_results["input_validator"],
326
+ validation_results["query_builder"],
327
+ validation_results["security_auditor"],
328
+ validation_results["database_adapters"],
329
+ validation_results["transaction_manager"],
330
+ ]
331
+ )
332
+
333
+ logger.info(f"Security configuration validation: {validation_results}")
334
+
335
+ except Exception as e:
336
+ logger.error(f"Security configuration validation failed: {e}")
337
+ validation_results["error"] = str(e)
338
+
339
+ return validation_results