memorisdk 2.3.0__tar.gz → 2.3.2__tar.gz

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 (77) hide show
  1. {memorisdk-2.3.0 → memorisdk-2.3.2}/PKG-INFO +24 -13
  2. {memorisdk-2.3.0 → memorisdk-2.3.2}/README.md +20 -9
  3. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/agents/memory_agent.py +4 -0
  4. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/agents/retrieval_agent.py +4 -0
  5. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/core/conversation.py +7 -1
  6. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/core/memory.py +16 -7
  7. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/mongodb_manager.py +29 -0
  8. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/sqlalchemy_manager.py +33 -0
  9. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/integrations/openai_integration.py +12 -27
  10. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/utils/logging.py +32 -81
  11. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/utils/validators.py +4 -4
  12. {memorisdk-2.3.0 → memorisdk-2.3.2}/memorisdk.egg-info/PKG-INFO +24 -13
  13. {memorisdk-2.3.0 → memorisdk-2.3.2}/memorisdk.egg-info/SOURCES.txt +2 -1
  14. {memorisdk-2.3.0 → memorisdk-2.3.2}/pyproject.toml +4 -4
  15. memorisdk-2.3.2/tests/test_memory_validation.py +39 -0
  16. {memorisdk-2.3.0 → memorisdk-2.3.2}/LICENSE +0 -0
  17. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/__init__.py +0 -0
  18. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/agents/__init__.py +0 -0
  19. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/agents/conscious_agent.py +0 -0
  20. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/config/__init__.py +0 -0
  21. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/config/manager.py +0 -0
  22. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/config/memory_manager.py +0 -0
  23. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/config/settings.py +0 -0
  24. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/core/__init__.py +0 -0
  25. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/core/database.py +0 -0
  26. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/core/providers.py +0 -0
  27. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/__init__.py +0 -0
  28. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/adapters/__init__.py +0 -0
  29. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/adapters/mongodb_adapter.py +0 -0
  30. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/adapters/mysql_adapter.py +0 -0
  31. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/adapters/postgresql_adapter.py +0 -0
  32. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/adapters/sqlite_adapter.py +0 -0
  33. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/auto_creator.py +0 -0
  34. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/connection_utils.py +0 -0
  35. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/connectors/__init__.py +0 -0
  36. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/connectors/base_connector.py +0 -0
  37. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/connectors/mongodb_connector.py +0 -0
  38. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/connectors/mysql_connector.py +0 -0
  39. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/connectors/postgres_connector.py +0 -0
  40. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/connectors/sqlite_connector.py +0 -0
  41. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/models.py +0 -0
  42. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/queries/__init__.py +0 -0
  43. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/queries/base_queries.py +0 -0
  44. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/queries/chat_queries.py +0 -0
  45. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/queries/entity_queries.py +0 -0
  46. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/queries/memory_queries.py +0 -0
  47. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/query_translator.py +0 -0
  48. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/schema_generators/__init__.py +0 -0
  49. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/schema_generators/mongodb_schema_generator.py +0 -0
  50. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/schema_generators/mysql_schema_generator.py +0 -0
  51. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/search/__init__.py +0 -0
  52. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/search/mongodb_search_adapter.py +0 -0
  53. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/search/mysql_search_adapter.py +0 -0
  54. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/search/sqlite_search_adapter.py +0 -0
  55. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/search_service.py +0 -0
  56. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/templates/__init__.py +0 -0
  57. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/templates/basic_template.py +0 -0
  58. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/database/templates/schemas/__init__.py +0 -0
  59. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/integrations/__init__.py +0 -0
  60. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/integrations/anthropic_integration.py +0 -0
  61. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/integrations/litellm_integration.py +0 -0
  62. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/tools/__init__.py +0 -0
  63. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/tools/memory_tool.py +0 -0
  64. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/utils/__init__.py +0 -0
  65. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/utils/exceptions.py +0 -0
  66. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/utils/helpers.py +0 -0
  67. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/utils/input_validator.py +0 -0
  68. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/utils/pydantic_models.py +0 -0
  69. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/utils/query_builder.py +0 -0
  70. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/utils/schemas.py +0 -0
  71. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/utils/security_audit.py +0 -0
  72. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/utils/security_integration.py +0 -0
  73. {memorisdk-2.3.0 → memorisdk-2.3.2}/memori/utils/transaction_manager.py +0 -0
  74. {memorisdk-2.3.0 → memorisdk-2.3.2}/memorisdk.egg-info/dependency_links.txt +0 -0
  75. {memorisdk-2.3.0 → memorisdk-2.3.2}/memorisdk.egg-info/requires.txt +0 -0
  76. {memorisdk-2.3.0 → memorisdk-2.3.2}/memorisdk.egg-info/top_level.txt +0 -0
  77. {memorisdk-2.3.0 → memorisdk-2.3.2}/setup.cfg +0 -0
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memorisdk
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Summary: The Open-Source Memory Layer for AI Agents & Multi-Agent Systems
5
- Author-email: GibsonAI Team <noc@gibsonai.com>
5
+ Author-email: Memori Labs Team <noc@memorilabs.ai>
6
6
  License: Apache-2.0
7
- Project-URL: Homepage, https://github.com/GibsonAI/memori
8
- Project-URL: Documentation, https://memori.gibsonai.com/docs
7
+ Project-URL: Homepage, https://memorilabs.ai
8
+ Project-URL: Documentation, https://www.gibsonai.com/docs/memori
9
9
  Project-URL: Repository, https://github.com/GibsonAI/memori.git
10
10
  Project-URL: Bug Tracker, https://github.com/GibsonAI/memori/issues
11
11
  Project-URL: Changelog, https://github.com/GibsonAI/memori/blob/main/CHANGELOG.md
@@ -95,9 +95,7 @@ Requires-Dist: pandas>=2.0.0; extra == "all"
95
95
  Requires-Dist: plotly>=5.17.0; extra == "all"
96
96
  Dynamic: license-file
97
97
 
98
- [![GibsonAI](https://github.com/user-attachments/assets/878e341b-5a93-4489-a398-abeca91b6b11)](https://gibsonai.com/)
99
-
100
- # memori
98
+ [![Memori Labs](https://s3.us-east-1.amazonaws.com/images.memorilabs.ai/banner.png)](https://memorilabs.ai/)
101
99
 
102
100
  <p align="center">
103
101
  <strong>An open-source SQL-Native memory engine for AI</strong>
@@ -108,9 +106,9 @@ Dynamic: license-file
108
106
  </p>
109
107
 
110
108
  <p align="center">
111
- <a href="https://memori.gibsonai.com/docs">Learn more</a>
109
+ <a href="https://www.gibsonai.com/docs/memori">Learn more</a>
112
110
  ·
113
- <a href="https://www.gibsonai.com/discord">Join Discord</a>
111
+ <a href="https://discord.gg/abD4eGym6v">Join Discord</a>
114
112
  </p>
115
113
 
116
114
  <p align="center">
@@ -120,14 +118,20 @@ Dynamic: license-file
120
118
  <a href="https://pepy.tech/projects/memorisdk">
121
119
  <img src="https://static.pepy.tech/badge/memorisdk" alt="Downloads">
122
120
  </a>
123
- <a href="https://opensource.org/licenses/MIT">
124
- <img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT">
121
+ <a href="https://opensource.org/license/apache-2-0">
122
+ <img src="https://img.shields.io/badge/license-Apache%20License%202.0-blue" alt="License: Apache 2.0">
125
123
  </a>
126
124
  <a href="https://www.python.org/downloads/">
127
125
  <img src="https://img.shields.io/badge/python-3.8+-blue.svg" alt="Python 3.8+">
128
126
  </a>
129
127
  </p>
130
128
 
129
+ <p align="center">
130
+ <a href="https://github.com/GibsonAI/memori/stargazers">
131
+ <img src="https://img.shields.io/badge/⭐%20Give%20a%20Star-Support%20the%20project-orange?style=for-the-badge" alt="Give a Star">
132
+ </a>
133
+ </p>
134
+
131
135
  ---
132
136
 
133
137
  ## What is Memori
@@ -206,6 +210,8 @@ print("\n💡 Notice: Memori automatically knows about your FastAPI Python proje
206
210
 
207
211
  ---
208
212
 
213
+ ⭐️ **Enjoying Memori?** Give us a star to support open development
214
+
209
215
  > By default, Memori uses in-memory SQLite database. Get **FREE** serverless database instance in [GibsonAI](https://app.gibsonai.com/signup) platform.
210
216
 
211
217
  **🚀 Ready to explore more?**
@@ -326,6 +332,7 @@ memori = Memori(
326
332
  database_connect="sqlite:///my_memory.db",
327
333
  template="basic",
328
334
  conscious_ingest=True, # One-shot context injection
335
+ conscious_memory_limit=100, # Must be an integer between 1 and 500
329
336
  openai_api_key="sk-..."
330
337
  )
331
338
 
@@ -503,11 +510,15 @@ Explore Memori's capabilities through these interactive demonstrations:
503
510
  ## 🤝 Contributing
504
511
 
505
512
  - See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup and guidelines.
506
- - Community: [Discord](https://www.gibsonai.com/discord)
513
+ - Community: [Discord](https://discord.gg/abD4eGym6v)
514
+
515
+ ## ⭐️ Star us on GitHub to support the project
516
+
517
+ [![Star History Chart](https://api.star-history.com/svg?repos=GibsonAI/memori&type=date&legend=top-left)](https://www.star-history.com/#GibsonAI/memori&type=date&legend=top-left)
507
518
 
508
519
  ## 📄 License
509
520
 
510
- MIT License - see [LICENSE](./LICENSE) for details.
521
+ Apache 2.0 License - see [LICENSE](./LICENSE) for details.
511
522
 
512
523
  ---
513
524
 
@@ -1,6 +1,4 @@
1
- [![GibsonAI](https://github.com/user-attachments/assets/878e341b-5a93-4489-a398-abeca91b6b11)](https://gibsonai.com/)
2
-
3
- # memori
1
+ [![Memori Labs](https://s3.us-east-1.amazonaws.com/images.memorilabs.ai/banner.png)](https://memorilabs.ai/)
4
2
 
5
3
  <p align="center">
6
4
  <strong>An open-source SQL-Native memory engine for AI</strong>
@@ -11,9 +9,9 @@
11
9
  </p>
12
10
 
13
11
  <p align="center">
14
- <a href="https://memori.gibsonai.com/docs">Learn more</a>
12
+ <a href="https://www.gibsonai.com/docs/memori">Learn more</a>
15
13
  ·
16
- <a href="https://www.gibsonai.com/discord">Join Discord</a>
14
+ <a href="https://discord.gg/abD4eGym6v">Join Discord</a>
17
15
  </p>
18
16
 
19
17
  <p align="center">
@@ -23,14 +21,20 @@
23
21
  <a href="https://pepy.tech/projects/memorisdk">
24
22
  <img src="https://static.pepy.tech/badge/memorisdk" alt="Downloads">
25
23
  </a>
26
- <a href="https://opensource.org/licenses/MIT">
27
- <img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT">
24
+ <a href="https://opensource.org/license/apache-2-0">
25
+ <img src="https://img.shields.io/badge/license-Apache%20License%202.0-blue" alt="License: Apache 2.0">
28
26
  </a>
29
27
  <a href="https://www.python.org/downloads/">
30
28
  <img src="https://img.shields.io/badge/python-3.8+-blue.svg" alt="Python 3.8+">
31
29
  </a>
32
30
  </p>
33
31
 
32
+ <p align="center">
33
+ <a href="https://github.com/GibsonAI/memori/stargazers">
34
+ <img src="https://img.shields.io/badge/⭐%20Give%20a%20Star-Support%20the%20project-orange?style=for-the-badge" alt="Give a Star">
35
+ </a>
36
+ </p>
37
+
34
38
  ---
35
39
 
36
40
  ## What is Memori
@@ -109,6 +113,8 @@ print("\n💡 Notice: Memori automatically knows about your FastAPI Python proje
109
113
 
110
114
  ---
111
115
 
116
+ ⭐️ **Enjoying Memori?** Give us a star to support open development
117
+
112
118
  > By default, Memori uses in-memory SQLite database. Get **FREE** serverless database instance in [GibsonAI](https://app.gibsonai.com/signup) platform.
113
119
 
114
120
  **🚀 Ready to explore more?**
@@ -229,6 +235,7 @@ memori = Memori(
229
235
  database_connect="sqlite:///my_memory.db",
230
236
  template="basic",
231
237
  conscious_ingest=True, # One-shot context injection
238
+ conscious_memory_limit=100, # Must be an integer between 1 and 500
232
239
  openai_api_key="sk-..."
233
240
  )
234
241
 
@@ -406,11 +413,15 @@ Explore Memori's capabilities through these interactive demonstrations:
406
413
  ## 🤝 Contributing
407
414
 
408
415
  - See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup and guidelines.
409
- - Community: [Discord](https://www.gibsonai.com/discord)
416
+ - Community: [Discord](https://discord.gg/abD4eGym6v)
417
+
418
+ ## ⭐️ Star us on GitHub to support the project
419
+
420
+ [![Star History Chart](https://api.star-history.com/svg?repos=GibsonAI/memori&type=date&legend=top-left)](https://www.star-history.com/#GibsonAI/memori&type=date&legend=top-left)
410
421
 
411
422
  ## 📄 License
412
423
 
413
- MIT License - see [LICENSE](./LICENSE) for details.
424
+ Apache 2.0 License - see [LICENSE](./LICENSE) for details.
414
425
 
415
426
  ---
416
427
 
@@ -204,6 +204,9 @@ CONVERSATION CONTEXT:
204
204
  "content": f"Process this conversation for enhanced memory storage:\n\n{conversation_text}\n{context_info}",
205
205
  },
206
206
  ],
207
+ metadata=[
208
+ "INTERNAL_MEMORY_PROCESSING"
209
+ ], # Internal metadata tag
207
210
  response_format=ProcessedLongTermMemory,
208
211
  temperature=0.1, # Low temperature for consistent processing
209
212
  )
@@ -417,6 +420,7 @@ CONVERSATION CONTEXT:
417
420
  "content": f"Process this conversation for enhanced memory storage:\n\n{conversation_text}\n{context_info}",
418
421
  },
419
422
  ],
423
+ metadata=["INTERNAL_MEMORY_PROCESSING"], # Internal metadata tag
420
424
  temperature=0.1, # Low temperature for consistent processing
421
425
  max_tokens=2000, # Ensure enough tokens for full response
422
426
  )
@@ -149,6 +149,9 @@ Be strategic and comprehensive in your search planning."""
149
149
  "content": prompt,
150
150
  },
151
151
  ],
152
+ metadata=[
153
+ "INTERNAL_MEMORY_PROCESSING"
154
+ ], # Internal metadata tag
152
155
  response_format=MemorySearchQuery,
153
156
  temperature=0.1,
154
157
  )
@@ -656,6 +659,7 @@ Be strategic and comprehensive in your search planning."""
656
659
  "content": prompt,
657
660
  },
658
661
  ],
662
+ metadata=["INTERNAL_MEMORY_PROCESSING"], # Internal metadata tag
659
663
  temperature=0.1,
660
664
  max_tokens=1000, # Ensure enough tokens for full response
661
665
  )
@@ -242,8 +242,14 @@ class ConversationManager:
242
242
  if previous_messages:
243
243
  system_content += "\n--- Conversation History ---\n"
244
244
  for msg in previous_messages:
245
- role_label = "You" if msg["role"] == "assistant" else "User"
245
+ if msg["role"] == "assistant":
246
+ role_label = "Assistant"
247
+ elif msg["role"] == "user":
248
+ role_label = "User"
249
+ else:
250
+ role_label = msg["role"].capitalize()
246
251
  system_content += f"{role_label}: {msg['content']}\n"
252
+
247
253
  system_content += "--- End History ---\n"
248
254
  logger.debug(
249
255
  f"[CONTEXT] Added {len(previous_messages)} history messages | Session: {session_id[:8]}..."
@@ -15,6 +15,7 @@ try:
15
15
  import litellm # noqa: F401
16
16
  from litellm import success_callback # noqa: F401
17
17
 
18
+ _ = litellm # Mark as intentionally imported
18
19
  LITELLM_AVAILABLE = True
19
20
  except ImportError:
20
21
  LITELLM_AVAILABLE = False
@@ -111,9 +112,15 @@ class Memori:
111
112
  self.schema_init = schema_init
112
113
  self.database_prefix = database_prefix
113
114
  self.database_suffix = database_suffix
115
+
114
116
  # Validate conscious_memory_limit parameter
115
- if not isinstance(conscious_memory_limit, int) or conscious_memory_limit < 1:
116
- raise ValueError("conscious_memory_limit must be a positive integer")
117
+ if not isinstance(conscious_memory_limit, int) or isinstance(
118
+ conscious_memory_limit, bool
119
+ ):
120
+ raise TypeError("conscious_memory_limit must be an integer (not bool)")
121
+
122
+ if not (1 <= conscious_memory_limit <= 2000):
123
+ raise ValueError("conscious_memory_limit must be between 1 and 2000")
117
124
 
118
125
  self.conscious_memory_limit = conscious_memory_limit
119
126
 
@@ -1213,7 +1220,7 @@ class Memori:
1213
1220
  results[:3]
1214
1221
  ): # Log first 3 results for debugging
1215
1222
  logger.debug(
1216
- f"Auto-ingest: Result {i+1}: {type(result)} with keys: {list(result.keys()) if isinstance(result, dict) else 'N/A'}"
1223
+ f"Auto-ingest: Result {i + 1}: {type(result)} with keys: {list(result.keys()) if isinstance(result, dict) else 'N/A'}"
1217
1224
  )
1218
1225
  except Exception as db_search_e:
1219
1226
  logger.error(f"Auto-ingest: Database search failed: {db_search_e}")
@@ -2634,12 +2641,14 @@ class Memori:
2634
2641
  Get auto-ingest context as system prompt for direct injection.
2635
2642
  Returns relevant memories based on user input as formatted system prompt.
2636
2643
  Use this for auto_ingest mode.
2644
+
2645
+ Note: Context retrieval is handled by _get_auto_ingest_context().
2646
+ This function only formats pre-retrieved context.
2637
2647
  """
2638
2648
  try:
2639
- # For now, use recent short-term memories as a simple approach
2640
- # This avoids the search engine issues and still provides context
2641
- # TODO: Use user_input for intelligent context retrieval
2642
- context = self._get_conscious_context() # Get recent short-term memories
2649
+ # Get recent short-term memories as fallback context
2650
+ # The actual intelligent retrieval is handled by _get_auto_ingest_context()
2651
+ context = self._get_conscious_context()
2643
2652
 
2644
2653
  if not context:
2645
2654
  return ""
@@ -928,6 +928,28 @@ class MongoDBDatabaseManager:
928
928
  except Exception as e:
929
929
  logger.error(f"Failed to mark conscious memories processed: {e}")
930
930
 
931
+ def _check_milestone(self, memory_count: int):
932
+ """
933
+ Check and celebrate memory storage milestones to encourage user engagement.
934
+ Displays celebration messages at key milestones: 10, 50, 100, 500, 1000 memories.
935
+
936
+ Args:
937
+ memory_count: Current count of long-term memories
938
+ """
939
+ milestones = [10, 50, 100, 500, 1000]
940
+
941
+ if memory_count in milestones:
942
+ celebration_msg = (
943
+ f"\n{'=' * 60}\n"
944
+ f"🎉 Milestone Achieved: {memory_count} memories stored!\n"
945
+ f"{'=' * 60}\n"
946
+ f"⭐️ Loving Memori? Give us a star on GitHub!\n"
947
+ f"👉 https://github.com/GibsonAI/memori\n"
948
+ f"Your support helps us build better open AI memory tools ❤️\n"
949
+ f"{'=' * 60}\n"
950
+ )
951
+ logger.info(celebration_msg)
952
+
931
953
  def store_long_term_memory_enhanced(
932
954
  self, memory: ProcessedLongTermMemory, chat_id: str, namespace: str = "default"
933
955
  ) -> str:
@@ -1000,6 +1022,13 @@ class MongoDBDatabaseManager:
1000
1022
  collection.insert_one(document)
1001
1023
 
1002
1024
  logger.debug(f"Stored enhanced long-term memory {memory_id}")
1025
+
1026
+ # Get current memory count and check for milestones
1027
+ total_memories = collection.count_documents({"namespace": namespace})
1028
+
1029
+ # Celebrate milestone if reached
1030
+ self._check_milestone(total_memories)
1031
+
1003
1032
  return memory_id
1004
1033
 
1005
1034
  except Exception as e:
@@ -572,6 +572,28 @@ class SQLAlchemyDatabaseManager:
572
572
  except SQLAlchemyError as e:
573
573
  raise DatabaseError(f"Failed to get chat history: {e}")
574
574
 
575
+ def _check_milestone(self, memory_count: int):
576
+ """
577
+ Check and celebrate memory storage milestones to encourage user engagement.
578
+ Displays celebration messages at key milestones: 10, 50, 100, 500, 1000 memories.
579
+
580
+ Args:
581
+ memory_count: Current count of long-term memories
582
+ """
583
+ milestones = [10, 50, 100, 500, 1000]
584
+
585
+ if memory_count in milestones:
586
+ celebration_msg = (
587
+ f"\n{'=' * 60}\n"
588
+ f"🎉 Milestone Achieved: {memory_count} memories stored!\n"
589
+ f"{'=' * 60}\n"
590
+ f"⭐️ Loving Memori? Give us a star on GitHub!\n"
591
+ f"👉 https://github.com/GibsonAI/memori\n"
592
+ f"Your support helps us build better open AI memory tools ❤️\n"
593
+ f"{'=' * 60}\n"
594
+ )
595
+ logger.info(celebration_msg)
596
+
575
597
  def store_long_term_memory_enhanced(
576
598
  self, memory: ProcessedLongTermMemory, chat_id: str, namespace: str = "default"
577
599
  ) -> str:
@@ -618,6 +640,17 @@ class SQLAlchemyDatabaseManager:
618
640
  session.commit()
619
641
 
620
642
  logger.debug(f"Stored enhanced long-term memory {memory_id}")
643
+
644
+ # Get current memory count and check for milestones
645
+ total_memories = (
646
+ session.query(LongTermMemory)
647
+ .filter(LongTermMemory.namespace == namespace)
648
+ .count()
649
+ )
650
+
651
+ # Celebrate milestone if reached
652
+ self._check_milestone(total_memories)
653
+
621
654
  return memory_id
622
655
 
623
656
  except SQLAlchemyError as e:
@@ -246,33 +246,18 @@ class OpenAIInterceptor:
246
246
  def _is_internal_agent_call(cls, json_data):
247
247
  """Check if this is an internal agent processing call that should not be recorded."""
248
248
  try:
249
- messages = json_data.get("messages", [])
250
- for message in messages:
251
- content = message.get("content", "")
252
- if isinstance(content, str):
253
- # Check for specific internal agent processing patterns
254
- # Made patterns more specific to avoid false positives
255
- internal_patterns = [
256
- "Process this conversation for enhanced memory storage:",
257
- "Enhanced memory processing:",
258
- "Memory classification:",
259
- "Search for relevant memories:",
260
- "Analyze conversation for:",
261
- "Extract entities from:",
262
- "Categorize the following conversation:",
263
- # More specific patterns to avoid blocking legitimate conversations
264
- "INTERNAL_MEMORY_PROCESSING:",
265
- "AGENT_PROCESSING_MODE:",
266
- "MEMORY_AGENT_TASK:",
267
- ]
268
-
269
- # Only flag as internal if it matches specific patterns AND has no user role
270
- for pattern in internal_patterns:
271
- if pattern in content:
272
- # Double-check: if this is a user message, don't filter it
273
- if message.get("role") == "user":
274
- continue
275
- return True
249
+ openai_metadata = json_data.get("metadata", [])
250
+
251
+ # Check for specific internal agent metadata flags
252
+ if isinstance(openai_metadata, list):
253
+ internal_metadata = [
254
+ "INTERNAL_MEMORY_PROCESSING", # used in memory agent and retrieval agent
255
+ "AGENT_PROCESSING_MODE",
256
+ "MEMORY_AGENT_TASK",
257
+ ]
258
+ for internal in internal_metadata:
259
+ if internal in openai_metadata:
260
+ return True
276
261
 
277
262
  return False
278
263
 
@@ -2,6 +2,7 @@
2
2
  Centralized logging configuration for Memoriai
3
3
  """
4
4
 
5
+ import logging
5
6
  import sys
6
7
  from pathlib import Path
7
8
  from typing import Any
@@ -22,41 +23,35 @@ class LoggingManager:
22
23
  def setup_logging(cls, settings: LoggingSettings, verbose: bool = False) -> None:
23
24
  """Setup logging configuration"""
24
25
  try:
25
- # Remove default handler if it exists
26
26
  if not cls._initialized:
27
27
  logger.remove()
28
28
 
29
29
  if verbose:
30
- # When verbose mode is enabled, disable all other loggers and show only loguru
31
30
  cls._disable_other_loggers()
32
31
 
33
- # Configure console logging with DEBUG level and full formatting
34
32
  logger.add(
35
33
  sys.stderr,
36
34
  level="DEBUG",
37
- format=settings.format,
35
+ format="<green>{time:HH:mm:ss}</green> | <level>{level:8}</level> | {message}",
38
36
  colorize=True,
39
37
  backtrace=True,
40
38
  diagnose=True,
41
39
  )
42
40
  else:
43
- # When verbose is False, minimize loguru output to essential logs only
44
41
  logger.add(
45
42
  sys.stderr,
46
- level="WARNING", # Only show warnings and errors
47
- format="<level>{level}</level>: {message}", # Simplified format
43
+ level="WARNING",
44
+ format="<level>{level}</level>: {message}",
48
45
  colorize=False,
49
46
  backtrace=False,
50
47
  diagnose=False,
51
48
  )
52
49
 
53
- # Configure file logging if enabled
54
50
  if settings.log_to_file:
55
51
  log_path = Path(settings.log_file_path)
56
52
  log_path.parent.mkdir(parents=True, exist_ok=True)
57
53
 
58
54
  if settings.structured_logging:
59
- # JSON structured logging
60
55
  logger.add(
61
56
  log_path,
62
57
  level=settings.level.value,
@@ -67,7 +62,6 @@ class LoggingManager:
67
62
  serialize=True,
68
63
  )
69
64
  else:
70
- # Regular text logging
71
65
  logger.add(
72
66
  log_path,
73
67
  level=settings.level.value,
@@ -96,7 +90,6 @@ class LoggingManager:
96
90
  raise ConfigurationError("Logging not initialized")
97
91
 
98
92
  try:
99
- # Remove existing handlers and recreate with new level
100
93
  logger.remove()
101
94
 
102
95
  if cls._current_config:
@@ -127,76 +120,34 @@ class LoggingManager:
127
120
 
128
121
  @classmethod
129
122
  def _disable_other_loggers(cls) -> None:
130
- """Disable all other loggers when verbose mode is enabled"""
131
- import logging
132
-
133
- # Set the root logger to CRITICAL and disable it
134
- root_logger = logging.getLogger()
135
- root_logger.setLevel(logging.CRITICAL)
136
- root_logger.disabled = True
137
-
138
- # Remove all handlers from the root logger
139
- for handler in root_logger.handlers[:]:
140
- root_logger.removeHandler(handler)
141
-
142
- # Disable common third-party library loggers
143
- third_party_loggers = [
144
- "urllib3",
145
- "requests",
146
- "httpx",
147
- "httpcore",
148
- "openai",
149
- "anthropic",
150
- "litellm",
151
- "sqlalchemy",
152
- "alembic",
153
- "asyncio",
154
- "concurrent.futures",
155
- "charset_normalizer",
156
- "certifi",
157
- "idna",
158
- ]
159
-
160
- for logger_name in third_party_loggers:
161
- lib_logger = logging.getLogger(logger_name)
162
- lib_logger.disabled = True
163
- lib_logger.setLevel(logging.CRITICAL)
164
- # Remove all handlers
165
- for handler in lib_logger.handlers[:]:
166
- lib_logger.removeHandler(handler)
167
-
168
- # Set all existing loggers to CRITICAL level and disable them
169
- for name in list(logging.Logger.manager.loggerDict.keys()):
170
- existing_logger = logging.getLogger(name)
171
- existing_logger.setLevel(logging.CRITICAL)
172
- existing_logger.disabled = True
173
- # Remove all handlers
174
- for handler in existing_logger.handlers[:]:
175
- existing_logger.removeHandler(handler)
176
-
177
- # Also disable warnings from the warnings module
178
- import warnings
179
-
180
- warnings.filterwarnings("ignore")
181
-
182
- # Override the logging module's basicConfig to prevent new loggers
183
- def disabled_basicConfig(*args, **kwargs):
184
- pass
185
-
186
- logging.basicConfig = disabled_basicConfig
187
-
188
- # Override the getLogger function to disable new loggers immediately
189
- original_getLogger = logging.getLogger
190
-
191
- def disabled_getLogger(name=None):
192
- logger_instance = original_getLogger(name)
193
- logger_instance.disabled = True
194
- logger_instance.setLevel(logging.CRITICAL)
195
- for handler in logger_instance.handlers[:]:
196
- logger_instance.removeHandler(handler)
197
- return logger_instance
198
-
199
- logging.getLogger = disabled_getLogger
123
+ """
124
+ Intercept all logs from the standard `logging` module and redirect them to Loguru.
125
+ This ensures all log output is controlled and formatted by Loguru.
126
+ """
127
+
128
+ class InterceptStandardLoggingHandler(logging.Handler):
129
+ def emit(self, record: logging.LogRecord) -> None:
130
+ try:
131
+ level = logger.level(record.levelname).name
132
+ except ValueError:
133
+ level = record.levelno
134
+
135
+ frame, depth = logging.currentframe(), 2
136
+ while (
137
+ frame is not None and frame.f_code.co_filename == logging.__file__
138
+ ):
139
+ frame = frame.f_back
140
+ depth += 1
141
+
142
+ formatted_message = f"[{record.name}] {record.getMessage()}"
143
+
144
+ logger.opt(depth=depth, exception=record.exc_info).log(
145
+ level, formatted_message
146
+ )
147
+
148
+ logging.basicConfig(
149
+ handlers=[InterceptStandardLoggingHandler()], level=0, force=True
150
+ )
200
151
 
201
152
 
202
153
  def get_logger(name: str = "memori") -> "logger":
@@ -58,12 +58,12 @@ class DataValidator:
58
58
  @classmethod
59
59
  def validate_namespace(cls, value: str, field_name: str = "namespace") -> str:
60
60
  """Validate namespace format"""
61
+ if value is None or (isinstance(value, str) and value.strip() == ""):
62
+ return "default"
63
+
61
64
  if not isinstance(value, str):
62
65
  raise ValidationError(f"{field_name} must be a string")
63
66
 
64
- if not value:
65
- raise ValidationError(f"{field_name} cannot be empty")
66
-
67
67
  if len(value) > 64:
68
68
  raise ValidationError(f"{field_name} cannot exceed 64 characters")
69
69
 
@@ -73,7 +73,7 @@ class DataValidator:
73
73
  f"{field_name} can only contain letters, numbers, underscores, and hyphens"
74
74
  )
75
75
 
76
- return value
76
+ return value.strip()
77
77
 
78
78
  @classmethod
79
79
  def validate_importance_score(
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memorisdk
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Summary: The Open-Source Memory Layer for AI Agents & Multi-Agent Systems
5
- Author-email: GibsonAI Team <noc@gibsonai.com>
5
+ Author-email: Memori Labs Team <noc@memorilabs.ai>
6
6
  License: Apache-2.0
7
- Project-URL: Homepage, https://github.com/GibsonAI/memori
8
- Project-URL: Documentation, https://memori.gibsonai.com/docs
7
+ Project-URL: Homepage, https://memorilabs.ai
8
+ Project-URL: Documentation, https://www.gibsonai.com/docs/memori
9
9
  Project-URL: Repository, https://github.com/GibsonAI/memori.git
10
10
  Project-URL: Bug Tracker, https://github.com/GibsonAI/memori/issues
11
11
  Project-URL: Changelog, https://github.com/GibsonAI/memori/blob/main/CHANGELOG.md
@@ -95,9 +95,7 @@ Requires-Dist: pandas>=2.0.0; extra == "all"
95
95
  Requires-Dist: plotly>=5.17.0; extra == "all"
96
96
  Dynamic: license-file
97
97
 
98
- [![GibsonAI](https://github.com/user-attachments/assets/878e341b-5a93-4489-a398-abeca91b6b11)](https://gibsonai.com/)
99
-
100
- # memori
98
+ [![Memori Labs](https://s3.us-east-1.amazonaws.com/images.memorilabs.ai/banner.png)](https://memorilabs.ai/)
101
99
 
102
100
  <p align="center">
103
101
  <strong>An open-source SQL-Native memory engine for AI</strong>
@@ -108,9 +106,9 @@ Dynamic: license-file
108
106
  </p>
109
107
 
110
108
  <p align="center">
111
- <a href="https://memori.gibsonai.com/docs">Learn more</a>
109
+ <a href="https://www.gibsonai.com/docs/memori">Learn more</a>
112
110
  ·
113
- <a href="https://www.gibsonai.com/discord">Join Discord</a>
111
+ <a href="https://discord.gg/abD4eGym6v">Join Discord</a>
114
112
  </p>
115
113
 
116
114
  <p align="center">
@@ -120,14 +118,20 @@ Dynamic: license-file
120
118
  <a href="https://pepy.tech/projects/memorisdk">
121
119
  <img src="https://static.pepy.tech/badge/memorisdk" alt="Downloads">
122
120
  </a>
123
- <a href="https://opensource.org/licenses/MIT">
124
- <img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT">
121
+ <a href="https://opensource.org/license/apache-2-0">
122
+ <img src="https://img.shields.io/badge/license-Apache%20License%202.0-blue" alt="License: Apache 2.0">
125
123
  </a>
126
124
  <a href="https://www.python.org/downloads/">
127
125
  <img src="https://img.shields.io/badge/python-3.8+-blue.svg" alt="Python 3.8+">
128
126
  </a>
129
127
  </p>
130
128
 
129
+ <p align="center">
130
+ <a href="https://github.com/GibsonAI/memori/stargazers">
131
+ <img src="https://img.shields.io/badge/⭐%20Give%20a%20Star-Support%20the%20project-orange?style=for-the-badge" alt="Give a Star">
132
+ </a>
133
+ </p>
134
+
131
135
  ---
132
136
 
133
137
  ## What is Memori
@@ -206,6 +210,8 @@ print("\n💡 Notice: Memori automatically knows about your FastAPI Python proje
206
210
 
207
211
  ---
208
212
 
213
+ ⭐️ **Enjoying Memori?** Give us a star to support open development
214
+
209
215
  > By default, Memori uses in-memory SQLite database. Get **FREE** serverless database instance in [GibsonAI](https://app.gibsonai.com/signup) platform.
210
216
 
211
217
  **🚀 Ready to explore more?**
@@ -326,6 +332,7 @@ memori = Memori(
326
332
  database_connect="sqlite:///my_memory.db",
327
333
  template="basic",
328
334
  conscious_ingest=True, # One-shot context injection
335
+ conscious_memory_limit=100, # Must be an integer between 1 and 500
329
336
  openai_api_key="sk-..."
330
337
  )
331
338
 
@@ -503,11 +510,15 @@ Explore Memori's capabilities through these interactive demonstrations:
503
510
  ## 🤝 Contributing
504
511
 
505
512
  - See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup and guidelines.
506
- - Community: [Discord](https://www.gibsonai.com/discord)
513
+ - Community: [Discord](https://discord.gg/abD4eGym6v)
514
+
515
+ ## ⭐️ Star us on GitHub to support the project
516
+
517
+ [![Star History Chart](https://api.star-history.com/svg?repos=GibsonAI/memori&type=date&legend=top-left)](https://www.star-history.com/#GibsonAI/memori&type=date&legend=top-left)
507
518
 
508
519
  ## 📄 License
509
520
 
510
- MIT License - see [LICENSE](./LICENSE) for details.
521
+ Apache 2.0 License - see [LICENSE](./LICENSE) for details.
511
522
 
512
523
  ---
513
524
 
@@ -71,4 +71,5 @@ memorisdk.egg-info/PKG-INFO
71
71
  memorisdk.egg-info/SOURCES.txt
72
72
  memorisdk.egg-info/dependency_links.txt
73
73
  memorisdk.egg-info/requires.txt
74
- memorisdk.egg-info/top_level.txt
74
+ memorisdk.egg-info/top_level.txt
75
+ tests/test_memory_validation.py
@@ -4,9 +4,9 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "memorisdk"
7
- version = "2.3.0"
7
+ version = "2.3.2"
8
8
  description = "The Open-Source Memory Layer for AI Agents & Multi-Agent Systems"
9
- authors = [{name = "GibsonAI Team", email = "noc@gibsonai.com"}]
9
+ authors = [{name = "Memori Labs Team", email = "noc@memorilabs.ai"}]
10
10
  license = {text = "Apache-2.0"}
11
11
  readme = "README.md"
12
12
  requires-python = ">=3.10"
@@ -112,8 +112,8 @@ all = [
112
112
  ]
113
113
 
114
114
  [project.urls]
115
- Homepage = "https://github.com/GibsonAI/memori"
116
- Documentation = "https://memori.gibsonai.com/docs"
115
+ Homepage = "https://memorilabs.ai"
116
+ Documentation = "https://www.gibsonai.com/docs/memori"
117
117
  Repository = "https://github.com/GibsonAI/memori.git"
118
118
  "Bug Tracker" = "https://github.com/GibsonAI/memori/issues"
119
119
  "Changelog" = "https://github.com/GibsonAI/memori/blob/main/CHANGELOG.md"
@@ -0,0 +1,39 @@
1
+ import sys
2
+ from pathlib import Path
3
+
4
+ import pytest
5
+
6
+ # Add the root project folder to the Python path
7
+ sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
8
+
9
+ from memori.core.memory import Memori
10
+
11
+
12
+ def test_conscious_memory_limit_valid_values():
13
+ """Valid conscious_memory_limit values should not raise errors"""
14
+ try:
15
+ Memori(conscious_memory_limit=1)
16
+ Memori(conscious_memory_limit=500)
17
+ Memori(conscious_memory_limit=1500)
18
+ Memori(conscious_memory_limit=2000)
19
+ except Exception as e:
20
+ pytest.fail(f"Unexpected exception raised: {e}")
21
+
22
+
23
+ def test_conscious_memory_limit_invalid_low():
24
+ """Values below 1 should raise ValueError"""
25
+ with pytest.raises(ValueError):
26
+ Memori(conscious_memory_limit=0)
27
+
28
+
29
+ def test_conscious_memory_limit_invalid_high():
30
+ """Values above 2000 should raise ValueError"""
31
+ with pytest.raises(ValueError):
32
+ Memori(conscious_memory_limit=3000)
33
+
34
+
35
+ @pytest.mark.parametrize("invalid_value", ["high", 3.14, None, True, False])
36
+ def test_conscious_memory_limit_invalid_types(invalid_value):
37
+ """Non-integer or boolean types should raise TypeError"""
38
+ with pytest.raises(TypeError):
39
+ Memori(conscious_memory_limit=invalid_value)
File without changes
File without changes
File without changes