mdb-engine 0.7.0__py3-none-any.whl → 0.7.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.
- mdb_engine/__init__.py +7 -13
- mdb_engine/cli/main.py +1 -1
- mdb_engine/core/engine.py +58 -4
- mdb_engine/core/service_initialization.py +63 -7
- {mdb_engine-0.7.0.dist-info → mdb_engine-0.7.1.dist-info}/METADATA +1 -1
- {mdb_engine-0.7.0.dist-info → mdb_engine-0.7.1.dist-info}/RECORD +10 -10
- {mdb_engine-0.7.0.dist-info → mdb_engine-0.7.1.dist-info}/WHEEL +0 -0
- {mdb_engine-0.7.0.dist-info → mdb_engine-0.7.1.dist-info}/entry_points.txt +0 -0
- {mdb_engine-0.7.0.dist-info → mdb_engine-0.7.1.dist-info}/licenses/LICENSE +0 -0
- {mdb_engine-0.7.0.dist-info → mdb_engine-0.7.1.dist-info}/top_level.txt +0 -0
mdb_engine/__init__.py
CHANGED
|
@@ -82,19 +82,13 @@ from .repositories import Entity, MongoRepository, Repository, UnitOfWork
|
|
|
82
82
|
from .utils import clean_mongo_doc, clean_mongo_docs
|
|
83
83
|
|
|
84
84
|
__version__ = (
|
|
85
|
-
"0.
|
|
86
|
-
# -
|
|
87
|
-
# -
|
|
88
|
-
# -
|
|
89
|
-
# -
|
|
90
|
-
# -
|
|
91
|
-
# -
|
|
92
|
-
# - ENHANCED: WebSocket authentication with session key support
|
|
93
|
-
# - ENHANCED: CSRF middleware session key validation
|
|
94
|
-
# - ENHANCED: Multi-app WebSocket routing with session keys
|
|
95
|
-
# - BACKWARD COMPATIBLE: Cookie-based authentication fallback
|
|
96
|
-
# - UPDATED: All documentation for secure-by-default approach
|
|
97
|
-
# - COMPREHENSIVE: Unit and integration tests for session keys
|
|
85
|
+
"0.7.1" # Memory service initialization fix for multi-app setups
|
|
86
|
+
# - FIXED: Memory service initialization in create_multi_app context
|
|
87
|
+
# - FIXED: get_memory_service() now returns service when memory_config.enabled: true
|
|
88
|
+
# - ENHANCED: Explicit memory service initialization in create_multi_app lifespan
|
|
89
|
+
# - ENHANCED: Better error handling and logging for memory service initialization
|
|
90
|
+
# - ADDED: Comprehensive integration tests for memory service in multi-app context
|
|
91
|
+
# - ADDED: Unit tests for memory service initialization edge cases
|
|
98
92
|
)
|
|
99
93
|
|
|
100
94
|
__all__ = [
|
mdb_engine/cli/main.py
CHANGED
mdb_engine/core/engine.py
CHANGED
|
@@ -36,6 +36,11 @@ from typing import TYPE_CHECKING, Any, Optional
|
|
|
36
36
|
from motor.motor_asyncio import AsyncIOMotorClient
|
|
37
37
|
from pymongo.errors import PyMongoError
|
|
38
38
|
|
|
39
|
+
try:
|
|
40
|
+
from openai import OpenAIError
|
|
41
|
+
except ImportError:
|
|
42
|
+
OpenAIError = RuntimeError
|
|
43
|
+
|
|
39
44
|
if TYPE_CHECKING:
|
|
40
45
|
from fastapi import FastAPI
|
|
41
46
|
|
|
@@ -2672,7 +2677,7 @@ class MongoDBEngine:
|
|
|
2672
2677
|
)
|
|
2673
2678
|
|
|
2674
2679
|
@asynccontextmanager
|
|
2675
|
-
async def lifespan(app: FastAPI):
|
|
2680
|
+
async def lifespan(app: FastAPI): # noqa: C901
|
|
2676
2681
|
"""Lifespan context manager for parent app."""
|
|
2677
2682
|
nonlocal mounted_apps, shared_user_pool_initialized
|
|
2678
2683
|
|
|
@@ -2911,11 +2916,60 @@ class MongoDBEngine:
|
|
|
2911
2916
|
child_app.add_middleware(middleware_class)
|
|
2912
2917
|
logger.debug(f"Added AppContextMiddleware to child app '{slug}'")
|
|
2913
2918
|
|
|
2914
|
-
# CRITICAL FIX: Register WebSocket routes on parent app BEFORE mounting
|
|
2915
|
-
# This ensures WebSocket routes are checked before mounted app routes
|
|
2916
|
-
# Mounted apps create catch-all routes that intercept /app-slug/* paths
|
|
2917
2919
|
await _register_websocket_routes(app, app_manifest_data, slug, path_prefix)
|
|
2918
2920
|
|
|
2921
|
+
memory_config = app_manifest_data.get("memory_config")
|
|
2922
|
+
if memory_config and memory_config.get("enabled", False):
|
|
2923
|
+
if engine._service_initializer: # noqa: SLF001
|
|
2924
|
+
try:
|
|
2925
|
+
await engine._service_initializer.initialize_memory_service( # noqa: SLF001
|
|
2926
|
+
slug, memory_config
|
|
2927
|
+
)
|
|
2928
|
+
logger.info(
|
|
2929
|
+
f"Memory service initialized for mounted app '{slug}' "
|
|
2930
|
+
f"in multi-app context"
|
|
2931
|
+
)
|
|
2932
|
+
except OpenAIError as e:
|
|
2933
|
+
logger.warning(
|
|
2934
|
+
f"Memory service initialization skipped for mounted app "
|
|
2935
|
+
f"'{slug}': OpenAI API error. {e}",
|
|
2936
|
+
extra={"app_slug": slug, "error": str(e)},
|
|
2937
|
+
)
|
|
2938
|
+
except (
|
|
2939
|
+
ImportError,
|
|
2940
|
+
AttributeError,
|
|
2941
|
+
TypeError,
|
|
2942
|
+
ValueError,
|
|
2943
|
+
RuntimeError,
|
|
2944
|
+
ConnectionError,
|
|
2945
|
+
OSError,
|
|
2946
|
+
) as e:
|
|
2947
|
+
error_msg = str(e).lower()
|
|
2948
|
+
error_type = type(e).__name__
|
|
2949
|
+
is_api_key_error = (
|
|
2950
|
+
"api_key" in error_msg
|
|
2951
|
+
or "api key" in error_msg
|
|
2952
|
+
or "openai" in error_type.lower()
|
|
2953
|
+
)
|
|
2954
|
+
if is_api_key_error:
|
|
2955
|
+
logger.warning(
|
|
2956
|
+
f"Memory service initialization skipped for mounted app "
|
|
2957
|
+
f"'{slug}': Missing API key or configuration. {e}",
|
|
2958
|
+
extra={"app_slug": slug, "error": str(e)},
|
|
2959
|
+
)
|
|
2960
|
+
else:
|
|
2961
|
+
logger.error(
|
|
2962
|
+
f"Failed to initialize memory service for mounted app "
|
|
2963
|
+
f"'{slug}': {e}",
|
|
2964
|
+
exc_info=True,
|
|
2965
|
+
extra={"app_slug": slug, "error": str(e)},
|
|
2966
|
+
)
|
|
2967
|
+
else:
|
|
2968
|
+
logger.warning(
|
|
2969
|
+
f"Memory service requested for '{slug}' but "
|
|
2970
|
+
f"service_initializer is not available"
|
|
2971
|
+
)
|
|
2972
|
+
|
|
2919
2973
|
# Mount child app at path prefix (AFTER WebSocket routes are registered)
|
|
2920
2974
|
app.mount(path_prefix, child_app)
|
|
2921
2975
|
|
|
@@ -26,6 +26,11 @@ from ..observability import get_logger as get_contextual_logger
|
|
|
26
26
|
logger = logging.getLogger(__name__)
|
|
27
27
|
contextual_logger = get_contextual_logger(__name__)
|
|
28
28
|
|
|
29
|
+
try:
|
|
30
|
+
from openai import OpenAIError
|
|
31
|
+
except ImportError:
|
|
32
|
+
OpenAIError = RuntimeError
|
|
33
|
+
|
|
29
34
|
|
|
30
35
|
class ServiceInitializer:
|
|
31
36
|
"""
|
|
@@ -54,7 +59,9 @@ class ServiceInitializer:
|
|
|
54
59
|
self._memory_services: dict[str, Any] = {}
|
|
55
60
|
self._websocket_configs: dict[str, dict[str, Any]] = {}
|
|
56
61
|
|
|
57
|
-
async def initialize_memory_service(
|
|
62
|
+
async def initialize_memory_service(
|
|
63
|
+
self, slug: str, memory_config: dict[str, Any] | None
|
|
64
|
+
) -> None:
|
|
58
65
|
"""
|
|
59
66
|
Initialize Mem0 memory service for an app.
|
|
60
67
|
|
|
@@ -63,8 +70,17 @@ class ServiceInitializer:
|
|
|
63
70
|
|
|
64
71
|
Args:
|
|
65
72
|
slug: App slug
|
|
66
|
-
memory_config: Memory configuration from manifest (already validated)
|
|
73
|
+
memory_config: Memory configuration from manifest (already validated).
|
|
74
|
+
Can be None or empty dict to skip initialization.
|
|
67
75
|
"""
|
|
76
|
+
# Handle None or empty config
|
|
77
|
+
if not memory_config:
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
# Check if memory is enabled (must be checked before import)
|
|
81
|
+
if not memory_config.get("enabled", False):
|
|
82
|
+
return
|
|
83
|
+
|
|
68
84
|
# Try to import Memory service (optional dependency)
|
|
69
85
|
try:
|
|
70
86
|
from ..memory import Mem0MemoryService, Mem0MemoryServiceError
|
|
@@ -145,12 +161,41 @@ class ServiceInitializer:
|
|
|
145
161
|
extra={"app_slug": slug, "error": str(e)},
|
|
146
162
|
exc_info=True,
|
|
147
163
|
)
|
|
148
|
-
except
|
|
149
|
-
contextual_logger.
|
|
150
|
-
f"
|
|
164
|
+
except OpenAIError as e:
|
|
165
|
+
contextual_logger.warning(
|
|
166
|
+
f"Memory service initialization skipped for app '{slug}': "
|
|
167
|
+
f"OpenAI API error. {e}",
|
|
151
168
|
extra={"app_slug": slug, "error": str(e)},
|
|
152
|
-
exc_info=True,
|
|
153
169
|
)
|
|
170
|
+
except (
|
|
171
|
+
ImportError,
|
|
172
|
+
AttributeError,
|
|
173
|
+
TypeError,
|
|
174
|
+
ValueError,
|
|
175
|
+
RuntimeError,
|
|
176
|
+
ConnectionError,
|
|
177
|
+
OSError,
|
|
178
|
+
) as e:
|
|
179
|
+
error_msg = str(e).lower()
|
|
180
|
+
error_type = type(e).__name__
|
|
181
|
+
is_api_key_error = (
|
|
182
|
+
"api_key" in error_msg
|
|
183
|
+
or "api key" in error_msg
|
|
184
|
+
or "openai" in error_type.lower()
|
|
185
|
+
or "openai" in error_msg
|
|
186
|
+
)
|
|
187
|
+
if is_api_key_error:
|
|
188
|
+
contextual_logger.warning(
|
|
189
|
+
f"Memory service initialization skipped for app '{slug}': "
|
|
190
|
+
f"Missing API key or configuration. {e}",
|
|
191
|
+
extra={"app_slug": slug, "error": str(e)},
|
|
192
|
+
)
|
|
193
|
+
else:
|
|
194
|
+
contextual_logger.error(
|
|
195
|
+
f"Error initializing memory service for app '{slug}': {e}",
|
|
196
|
+
extra={"app_slug": slug, "error": str(e)},
|
|
197
|
+
exc_info=True,
|
|
198
|
+
)
|
|
154
199
|
|
|
155
200
|
async def register_websockets(self, slug: str, websockets_config: dict[str, Any]) -> None:
|
|
156
201
|
"""
|
|
@@ -330,7 +375,18 @@ class ServiceInitializer:
|
|
|
330
375
|
extra={"app_slug": slug},
|
|
331
376
|
)
|
|
332
377
|
return None
|
|
333
|
-
|
|
378
|
+
return service
|
|
379
|
+
|
|
380
|
+
# Service not found - check if it should be initialized but wasn't
|
|
381
|
+
# This can happen in multi-app context if initialization was missed
|
|
382
|
+
# Note: We can't do async initialization here, so we just log a warning
|
|
383
|
+
# The explicit initialization in create_multi_app should handle this
|
|
384
|
+
contextual_logger.debug(
|
|
385
|
+
f"Memory service not found for '{slug}' - "
|
|
386
|
+
f"it may not be initialized yet or memory is disabled",
|
|
387
|
+
extra={"app_slug": slug},
|
|
388
|
+
)
|
|
389
|
+
return None
|
|
334
390
|
except (KeyError, AttributeError, TypeError) as e:
|
|
335
391
|
contextual_logger.error(
|
|
336
392
|
f"Error retrieving memory service for '{slug}': {e}",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
mdb_engine/README.md,sha256=T3EFGcPopY9LslYW3lxgG3hohWkAOmBNbYG0FDMUJiY,3502
|
|
2
|
-
mdb_engine/__init__.py,sha256=
|
|
2
|
+
mdb_engine/__init__.py,sha256=d2oenqa95hRBwXIVPmKBE8lo61ojOkxfcuuIzgSxLXc,3655
|
|
3
3
|
mdb_engine/config.py,sha256=DTAyxfKB8ogyI0v5QR9Y-SJOgXQr_eDBCKxNBSqEyLc,7269
|
|
4
4
|
mdb_engine/constants.py,sha256=eaotvW57TVOg7rRbLziGrVNoP7adgw_G9iVByHezc_A,7837
|
|
5
5
|
mdb_engine/dependencies.py,sha256=MJuYQhZ9ZGzXlip1ha5zba9Rvn04HDPWahJFJH81Q2s,14107
|
|
@@ -35,7 +35,7 @@ mdb_engine/auth/utils.py,sha256=YkexCo0xV37mpOJUI32cntRHVOUUS7r19TIMPWHcgpA,2734
|
|
|
35
35
|
mdb_engine/auth/websocket_sessions.py,sha256=7eFNagY2K3Rp1x7d_cO5JcpT-DrYkc__cmVhl6pAC2M,15081
|
|
36
36
|
mdb_engine/auth/websocket_tickets.py,sha256=VoIArcnQBtYqXRMs-5m7NSvCJB1dEeHrLl7j7yG-H-A,9887
|
|
37
37
|
mdb_engine/cli/__init__.py,sha256=PANRi4THmL34d1mawlqxIrnuItXMdqoMTq5Z1zHd7rM,301
|
|
38
|
-
mdb_engine/cli/main.py,sha256=
|
|
38
|
+
mdb_engine/cli/main.py,sha256=4bWBNgksfRgimolBfivITNvYRMaLTvngeVDcdm7ou6M,811
|
|
39
39
|
mdb_engine/cli/utils.py,sha256=bNRGJgdzxUjXAOVe1aoxWJ5M_IqtAE-eW4pfAkwiDDM,2760
|
|
40
40
|
mdb_engine/cli/commands/__init__.py,sha256=ZSzMhKdV9ILD5EbOSxDV9nURHo1e4bQ0c8AWpqsTEqM,115
|
|
41
41
|
mdb_engine/cli/commands/generate.py,sha256=VEcn7qNQkIPQlLEK3oXUBgYMwD-G0FyomXQcWTtKsbs,17304
|
|
@@ -48,12 +48,12 @@ mdb_engine/core/app_registration.py,sha256=w7wjrlNQsEekuDQkG6HM4Z5t00E65baEzncnh
|
|
|
48
48
|
mdb_engine/core/app_secrets.py,sha256=bo-syg9UUATibNyXEZs-0TTYWG-JaY-2S0yNSGA12n0,10524
|
|
49
49
|
mdb_engine/core/connection.py,sha256=XnwuPG34pJ7kJGJ84T0mhj1UZ6_CLz_9qZf6NRYGIS8,8346
|
|
50
50
|
mdb_engine/core/encryption.py,sha256=RZ5LPF5g28E3ZBn6v1IMw_oas7u9YGFtBcEj8lTi9LM,7515
|
|
51
|
-
mdb_engine/core/engine.py,sha256=
|
|
51
|
+
mdb_engine/core/engine.py,sha256=wSJ99FP3NRUejGCXliwi9fW_pVZPpLjdUMG8FsU5Kms,185252
|
|
52
52
|
mdb_engine/core/index_management.py,sha256=9-r7MIy3JnjQ35sGqsbj8K_I07vAUWtAVgSWC99lJcE,5555
|
|
53
53
|
mdb_engine/core/manifest.py,sha256=D3OGRjm1It8dmS3IMoxHckHUerhs5PtcQgPz8o5ZL9w,140785
|
|
54
54
|
mdb_engine/core/ray_integration.py,sha256=csAgICl2g7Plqy4N49MJU1Ca-lr8KZznAouXMMRwhG8,13706
|
|
55
55
|
mdb_engine/core/seeding.py,sha256=c5IhdwlqUf_4Q5FFTAhPLaHPaUr_Txo3z_DUwZmWsFs,6421
|
|
56
|
-
mdb_engine/core/service_initialization.py,sha256=
|
|
56
|
+
mdb_engine/core/service_initialization.py,sha256=N4varRswExBYahAgPfcPtNhqszOjm0JQ0u7r7mfFyqM,15018
|
|
57
57
|
mdb_engine/core/types.py,sha256=u0LDGE4A3txGDlc9PNoQX8jwVYFjJSw4K5LDnpatsNc,11254
|
|
58
58
|
mdb_engine/database/README.md,sha256=-31mVxBeVQaYsF3AD1-gQbD2NCYVcPjdFoA6sZ6b02Y,19354
|
|
59
59
|
mdb_engine/database/__init__.py,sha256=rrc3eZFli3K2zrvVdDbMBi8YkmoHYzP6JNT0AUBE5VU,981
|
|
@@ -91,9 +91,9 @@ mdb_engine/routing/__init__.py,sha256=reupjHi_RTc2ZBA4AH5XzobAmqy4EQIsfSUcTkFknU
|
|
|
91
91
|
mdb_engine/routing/websockets.py,sha256=jgdLsrSOKyBiY4yzE7XYXV1MOChLw2CIWpT6RDL23hk,51649
|
|
92
92
|
mdb_engine/utils/__init__.py,sha256=lDxQSGqkV4fVw5TWIk6FA6_eey_ZnEtMY0fir3cpAe8,236
|
|
93
93
|
mdb_engine/utils/mongo.py,sha256=Oqtv4tQdpiiZzrilGLEYQPo8Vmh8WsTQypxQs8Of53s,3369
|
|
94
|
-
mdb_engine-0.7.
|
|
95
|
-
mdb_engine-0.7.
|
|
96
|
-
mdb_engine-0.7.
|
|
97
|
-
mdb_engine-0.7.
|
|
98
|
-
mdb_engine-0.7.
|
|
99
|
-
mdb_engine-0.7.
|
|
94
|
+
mdb_engine-0.7.1.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
|
|
95
|
+
mdb_engine-0.7.1.dist-info/METADATA,sha256=GXZ-ojykqFCH5RLybnClAHWcNU9da-wXweOyZmH01tM,19695
|
|
96
|
+
mdb_engine-0.7.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
97
|
+
mdb_engine-0.7.1.dist-info/entry_points.txt,sha256=INCbYdFbBzJalwPwxliEzLmPfR57IvQ7RAXG_pn8cL8,48
|
|
98
|
+
mdb_engine-0.7.1.dist-info/top_level.txt,sha256=PH0UEBwTtgkm2vWvC9He_EOMn7hVn_Wg_Jyc0SmeO8k,11
|
|
99
|
+
mdb_engine-0.7.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|