spatial-memory-mcp 1.9.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.
- spatial_memory/__init__.py +97 -0
- spatial_memory/__main__.py +271 -0
- spatial_memory/adapters/__init__.py +7 -0
- spatial_memory/adapters/lancedb_repository.py +880 -0
- spatial_memory/config.py +769 -0
- spatial_memory/core/__init__.py +118 -0
- spatial_memory/core/cache.py +317 -0
- spatial_memory/core/circuit_breaker.py +297 -0
- spatial_memory/core/connection_pool.py +220 -0
- spatial_memory/core/consolidation_strategies.py +401 -0
- spatial_memory/core/database.py +3072 -0
- spatial_memory/core/db_idempotency.py +242 -0
- spatial_memory/core/db_indexes.py +576 -0
- spatial_memory/core/db_migrations.py +588 -0
- spatial_memory/core/db_search.py +512 -0
- spatial_memory/core/db_versioning.py +178 -0
- spatial_memory/core/embeddings.py +558 -0
- spatial_memory/core/errors.py +317 -0
- spatial_memory/core/file_security.py +701 -0
- spatial_memory/core/filesystem.py +178 -0
- spatial_memory/core/health.py +289 -0
- spatial_memory/core/helpers.py +79 -0
- spatial_memory/core/import_security.py +433 -0
- spatial_memory/core/lifecycle_ops.py +1067 -0
- spatial_memory/core/logging.py +194 -0
- spatial_memory/core/metrics.py +192 -0
- spatial_memory/core/models.py +660 -0
- spatial_memory/core/rate_limiter.py +326 -0
- spatial_memory/core/response_types.py +500 -0
- spatial_memory/core/security.py +588 -0
- spatial_memory/core/spatial_ops.py +430 -0
- spatial_memory/core/tracing.py +300 -0
- spatial_memory/core/utils.py +110 -0
- spatial_memory/core/validation.py +406 -0
- spatial_memory/factory.py +444 -0
- spatial_memory/migrations/__init__.py +40 -0
- spatial_memory/ports/__init__.py +11 -0
- spatial_memory/ports/repositories.py +630 -0
- spatial_memory/py.typed +0 -0
- spatial_memory/server.py +1214 -0
- spatial_memory/services/__init__.py +70 -0
- spatial_memory/services/decay_manager.py +411 -0
- spatial_memory/services/export_import.py +1031 -0
- spatial_memory/services/lifecycle.py +1139 -0
- spatial_memory/services/memory.py +412 -0
- spatial_memory/services/spatial.py +1152 -0
- spatial_memory/services/utility.py +429 -0
- spatial_memory/tools/__init__.py +5 -0
- spatial_memory/tools/definitions.py +695 -0
- spatial_memory/verify.py +140 -0
- spatial_memory_mcp-1.9.1.dist-info/METADATA +509 -0
- spatial_memory_mcp-1.9.1.dist-info/RECORD +55 -0
- spatial_memory_mcp-1.9.1.dist-info/WHEEL +4 -0
- spatial_memory_mcp-1.9.1.dist-info/entry_points.txt +2 -0
- spatial_memory_mcp-1.9.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
"""Service factory for dependency injection and initialization.
|
|
2
|
+
|
|
3
|
+
This module provides a factory pattern for creating and wiring all services
|
|
4
|
+
used by the SpatialMemoryServer. It centralizes configuration and dependency
|
|
5
|
+
injection, making the server initialization cleaner and services more testable.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
from spatial_memory.factory import ServiceFactory
|
|
9
|
+
|
|
10
|
+
factory = ServiceFactory(settings)
|
|
11
|
+
services = factory.create_all()
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
from dataclasses import dataclass
|
|
18
|
+
|
|
19
|
+
from spatial_memory.adapters.lancedb_repository import LanceDBMemoryRepository
|
|
20
|
+
from spatial_memory.config import Settings
|
|
21
|
+
from spatial_memory.core.cache import ResponseCache
|
|
22
|
+
from spatial_memory.core.database import Database
|
|
23
|
+
from spatial_memory.core.embeddings import EmbeddingService
|
|
24
|
+
from spatial_memory.core.models import AutoDecayConfig
|
|
25
|
+
from spatial_memory.core.rate_limiter import AgentAwareRateLimiter, RateLimiter
|
|
26
|
+
from spatial_memory.ports.repositories import (
|
|
27
|
+
EmbeddingServiceProtocol,
|
|
28
|
+
MemoryRepositoryProtocol,
|
|
29
|
+
)
|
|
30
|
+
from spatial_memory.services.decay_manager import DecayManager
|
|
31
|
+
from spatial_memory.services.export_import import ExportImportConfig, ExportImportService
|
|
32
|
+
from spatial_memory.services.lifecycle import LifecycleConfig, LifecycleService
|
|
33
|
+
from spatial_memory.services.memory import MemoryService
|
|
34
|
+
from spatial_memory.services.spatial import SpatialConfig, SpatialService
|
|
35
|
+
from spatial_memory.services.utility import UtilityConfig, UtilityService
|
|
36
|
+
|
|
37
|
+
logger = logging.getLogger(__name__)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass
|
|
41
|
+
class ServiceContainer:
|
|
42
|
+
"""Container for all initialized services.
|
|
43
|
+
|
|
44
|
+
Provides access to all service instances created by the factory.
|
|
45
|
+
This allows the server to access services through a single container
|
|
46
|
+
rather than managing individual references.
|
|
47
|
+
|
|
48
|
+
Attributes:
|
|
49
|
+
embeddings: Embedding service for vector generation.
|
|
50
|
+
database: Database connection and operations.
|
|
51
|
+
repository: Memory repository for CRUD operations.
|
|
52
|
+
memory: Memory service for remember/recall operations.
|
|
53
|
+
spatial: Spatial service for exploration operations.
|
|
54
|
+
lifecycle: Lifecycle service for decay/reinforce/consolidate.
|
|
55
|
+
utility: Utility service for stats/namespaces/hybrid search.
|
|
56
|
+
export_import: Export/import service for data portability.
|
|
57
|
+
decay_manager: Automatic decay manager for real-time importance decay.
|
|
58
|
+
rate_limiter: Simple rate limiter (if per-agent disabled).
|
|
59
|
+
agent_rate_limiter: Per-agent rate limiter (if enabled).
|
|
60
|
+
cache: Response cache for read operations.
|
|
61
|
+
per_agent_rate_limiting: Whether per-agent rate limiting is enabled.
|
|
62
|
+
cache_enabled: Whether response caching is enabled.
|
|
63
|
+
regions_cache_ttl: TTL for regions cache entries.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
embeddings: EmbeddingServiceProtocol
|
|
67
|
+
database: Database | None
|
|
68
|
+
repository: MemoryRepositoryProtocol
|
|
69
|
+
memory: MemoryService
|
|
70
|
+
spatial: SpatialService
|
|
71
|
+
lifecycle: LifecycleService
|
|
72
|
+
utility: UtilityService
|
|
73
|
+
export_import: ExportImportService
|
|
74
|
+
decay_manager: DecayManager | None
|
|
75
|
+
rate_limiter: RateLimiter | None
|
|
76
|
+
agent_rate_limiter: AgentAwareRateLimiter | None
|
|
77
|
+
cache: ResponseCache | None
|
|
78
|
+
per_agent_rate_limiting: bool
|
|
79
|
+
cache_enabled: bool
|
|
80
|
+
regions_cache_ttl: float
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class ServiceFactory:
|
|
84
|
+
"""Factory for creating and wiring all services.
|
|
85
|
+
|
|
86
|
+
Centralizes service creation with proper dependency injection.
|
|
87
|
+
This simplifies server initialization and improves testability.
|
|
88
|
+
|
|
89
|
+
Example:
|
|
90
|
+
factory = ServiceFactory(settings)
|
|
91
|
+
services = factory.create_all()
|
|
92
|
+
# Use services.memory, services.spatial, etc.
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
def __init__(
|
|
96
|
+
self,
|
|
97
|
+
settings: Settings,
|
|
98
|
+
repository: MemoryRepositoryProtocol | None = None,
|
|
99
|
+
embeddings: EmbeddingServiceProtocol | None = None,
|
|
100
|
+
) -> None:
|
|
101
|
+
"""Initialize the factory.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
settings: Application settings.
|
|
105
|
+
repository: Optional repository override for testing.
|
|
106
|
+
embeddings: Optional embeddings override for testing.
|
|
107
|
+
"""
|
|
108
|
+
self._settings = settings
|
|
109
|
+
self._injected_repository = repository
|
|
110
|
+
self._injected_embeddings = embeddings
|
|
111
|
+
|
|
112
|
+
def create_embedding_service(self) -> EmbeddingService:
|
|
113
|
+
"""Create the embedding service.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Configured EmbeddingService instance.
|
|
117
|
+
"""
|
|
118
|
+
return EmbeddingService(
|
|
119
|
+
model_name=self._settings.embedding_model,
|
|
120
|
+
openai_api_key=self._settings.openai_api_key,
|
|
121
|
+
backend=self._settings.embedding_backend, # type: ignore[arg-type]
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
def create_database(self, embedding_dim: int) -> Database:
|
|
125
|
+
"""Create the database connection.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
embedding_dim: Dimension of embedding vectors.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Configured Database instance.
|
|
132
|
+
"""
|
|
133
|
+
db = Database(
|
|
134
|
+
storage_path=self._settings.memory_path,
|
|
135
|
+
embedding_dim=embedding_dim,
|
|
136
|
+
auto_create_indexes=self._settings.auto_create_indexes,
|
|
137
|
+
vector_index_threshold=self._settings.vector_index_threshold,
|
|
138
|
+
enable_fts=self._settings.enable_fts_index,
|
|
139
|
+
index_nprobes=self._settings.index_nprobes,
|
|
140
|
+
index_refine_factor=self._settings.index_refine_factor,
|
|
141
|
+
max_retry_attempts=self._settings.max_retry_attempts,
|
|
142
|
+
retry_backoff_seconds=self._settings.retry_backoff_seconds,
|
|
143
|
+
read_consistency_interval_ms=self._settings.read_consistency_interval_ms,
|
|
144
|
+
index_wait_timeout_seconds=self._settings.index_wait_timeout_seconds,
|
|
145
|
+
fts_stem=self._settings.fts_stem,
|
|
146
|
+
fts_remove_stop_words=self._settings.fts_remove_stop_words,
|
|
147
|
+
fts_language=self._settings.fts_language,
|
|
148
|
+
index_type=self._settings.index_type,
|
|
149
|
+
hnsw_m=self._settings.hnsw_m,
|
|
150
|
+
hnsw_ef_construction=self._settings.hnsw_ef_construction,
|
|
151
|
+
enable_memory_expiration=self._settings.enable_memory_expiration,
|
|
152
|
+
default_memory_ttl_days=self._settings.default_memory_ttl_days,
|
|
153
|
+
acknowledge_network_filesystem_risk=self._settings.acknowledge_network_filesystem_risk,
|
|
154
|
+
)
|
|
155
|
+
db.connect()
|
|
156
|
+
return db
|
|
157
|
+
|
|
158
|
+
def create_repository(self, database: Database) -> LanceDBMemoryRepository:
|
|
159
|
+
"""Create the memory repository.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
database: Database instance.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
LanceDBMemoryRepository instance.
|
|
166
|
+
"""
|
|
167
|
+
return LanceDBMemoryRepository(database)
|
|
168
|
+
|
|
169
|
+
def create_memory_service(
|
|
170
|
+
self,
|
|
171
|
+
repository: MemoryRepositoryProtocol,
|
|
172
|
+
embeddings: EmbeddingServiceProtocol,
|
|
173
|
+
) -> MemoryService:
|
|
174
|
+
"""Create the memory service.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
repository: Memory repository.
|
|
178
|
+
embeddings: Embedding service.
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
Configured MemoryService instance.
|
|
182
|
+
"""
|
|
183
|
+
return MemoryService(
|
|
184
|
+
repository=repository,
|
|
185
|
+
embeddings=embeddings,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
def create_spatial_service(
|
|
189
|
+
self,
|
|
190
|
+
repository: MemoryRepositoryProtocol,
|
|
191
|
+
embeddings: EmbeddingServiceProtocol,
|
|
192
|
+
) -> SpatialService:
|
|
193
|
+
"""Create the spatial service.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
repository: Memory repository.
|
|
197
|
+
embeddings: Embedding service.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
Configured SpatialService instance.
|
|
201
|
+
"""
|
|
202
|
+
return SpatialService(
|
|
203
|
+
repository=repository,
|
|
204
|
+
embeddings=embeddings,
|
|
205
|
+
config=SpatialConfig(
|
|
206
|
+
journey_max_steps=self._settings.max_journey_steps,
|
|
207
|
+
wander_max_steps=self._settings.max_wander_steps,
|
|
208
|
+
regions_max_memories=self._settings.regions_max_memories,
|
|
209
|
+
visualize_max_memories=self._settings.max_visualize_memories,
|
|
210
|
+
visualize_n_neighbors=self._settings.umap_n_neighbors,
|
|
211
|
+
visualize_min_dist=self._settings.umap_min_dist,
|
|
212
|
+
visualize_similarity_threshold=self._settings.visualize_similarity_threshold,
|
|
213
|
+
),
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
def create_lifecycle_service(
|
|
217
|
+
self,
|
|
218
|
+
repository: MemoryRepositoryProtocol,
|
|
219
|
+
embeddings: EmbeddingServiceProtocol,
|
|
220
|
+
) -> LifecycleService:
|
|
221
|
+
"""Create the lifecycle service.
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
repository: Memory repository.
|
|
225
|
+
embeddings: Embedding service.
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
Configured LifecycleService instance.
|
|
229
|
+
"""
|
|
230
|
+
return LifecycleService(
|
|
231
|
+
repository=repository,
|
|
232
|
+
embeddings=embeddings,
|
|
233
|
+
config=LifecycleConfig(
|
|
234
|
+
decay_default_half_life_days=self._settings.decay_default_half_life_days,
|
|
235
|
+
decay_default_function=self._settings.decay_default_function,
|
|
236
|
+
decay_min_importance_floor=self._settings.decay_min_importance_floor,
|
|
237
|
+
decay_batch_size=self._settings.decay_batch_size,
|
|
238
|
+
reinforce_default_boost=self._settings.reinforce_default_boost,
|
|
239
|
+
reinforce_max_importance=self._settings.reinforce_max_importance,
|
|
240
|
+
extract_max_text_length=self._settings.extract_max_text_length,
|
|
241
|
+
extract_max_candidates=self._settings.extract_max_candidates,
|
|
242
|
+
extract_default_importance=self._settings.extract_default_importance,
|
|
243
|
+
extract_default_namespace=self._settings.extract_default_namespace,
|
|
244
|
+
consolidate_min_threshold=self._settings.consolidate_min_threshold,
|
|
245
|
+
consolidate_content_weight=self._settings.consolidate_content_weight,
|
|
246
|
+
consolidate_max_batch=self._settings.consolidate_max_batch,
|
|
247
|
+
),
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
def create_utility_service(
|
|
251
|
+
self,
|
|
252
|
+
repository: MemoryRepositoryProtocol,
|
|
253
|
+
embeddings: EmbeddingServiceProtocol,
|
|
254
|
+
) -> UtilityService:
|
|
255
|
+
"""Create the utility service.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
repository: Memory repository.
|
|
259
|
+
embeddings: Embedding service.
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
Configured UtilityService instance.
|
|
263
|
+
"""
|
|
264
|
+
return UtilityService(
|
|
265
|
+
repository=repository,
|
|
266
|
+
embeddings=embeddings,
|
|
267
|
+
config=UtilityConfig(
|
|
268
|
+
hybrid_default_alpha=self._settings.hybrid_default_alpha,
|
|
269
|
+
hybrid_min_alpha=self._settings.hybrid_min_alpha,
|
|
270
|
+
hybrid_max_alpha=self._settings.hybrid_max_alpha,
|
|
271
|
+
stats_include_index_details=True,
|
|
272
|
+
namespace_batch_size=self._settings.namespace_batch_size,
|
|
273
|
+
delete_namespace_require_confirmation=self._settings.destructive_require_namespace_confirmation,
|
|
274
|
+
),
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
def create_export_import_service(
|
|
278
|
+
self,
|
|
279
|
+
repository: MemoryRepositoryProtocol,
|
|
280
|
+
embeddings: EmbeddingServiceProtocol,
|
|
281
|
+
) -> ExportImportService:
|
|
282
|
+
"""Create the export/import service.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
repository: Memory repository.
|
|
286
|
+
embeddings: Embedding service.
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
Configured ExportImportService instance.
|
|
290
|
+
"""
|
|
291
|
+
return ExportImportService(
|
|
292
|
+
repository=repository,
|
|
293
|
+
embeddings=embeddings,
|
|
294
|
+
config=ExportImportConfig(
|
|
295
|
+
default_export_format=self._settings.export_default_format,
|
|
296
|
+
export_batch_size=self._settings.export_batch_size,
|
|
297
|
+
import_batch_size=self._settings.import_batch_size,
|
|
298
|
+
import_deduplicate=self._settings.import_deduplicate_default,
|
|
299
|
+
import_dedup_threshold=self._settings.import_dedup_threshold,
|
|
300
|
+
validate_on_import=self._settings.import_validate_vectors,
|
|
301
|
+
parquet_compression="zstd",
|
|
302
|
+
max_import_records=self._settings.import_max_records,
|
|
303
|
+
csv_include_vectors=self._settings.csv_include_vectors,
|
|
304
|
+
max_export_records=self._settings.max_export_records,
|
|
305
|
+
),
|
|
306
|
+
allowed_export_paths=self._settings.export_allowed_paths,
|
|
307
|
+
allowed_import_paths=self._settings.import_allowed_paths,
|
|
308
|
+
allow_symlinks=self._settings.export_allow_symlinks,
|
|
309
|
+
max_import_size_bytes=int(self._settings.import_max_file_size_mb * 1024 * 1024),
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
def create_rate_limiter(self) -> tuple[RateLimiter | None, AgentAwareRateLimiter | None, bool]:
|
|
313
|
+
"""Create rate limiter based on settings.
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
Tuple of (simple_limiter, agent_limiter, per_agent_enabled).
|
|
317
|
+
"""
|
|
318
|
+
per_agent = self._settings.rate_limit_per_agent_enabled
|
|
319
|
+
if per_agent:
|
|
320
|
+
return (
|
|
321
|
+
None,
|
|
322
|
+
AgentAwareRateLimiter(
|
|
323
|
+
global_rate=self._settings.embedding_rate_limit,
|
|
324
|
+
per_agent_rate=self._settings.rate_limit_per_agent_rate,
|
|
325
|
+
max_agents=self._settings.rate_limit_max_tracked_agents,
|
|
326
|
+
),
|
|
327
|
+
True,
|
|
328
|
+
)
|
|
329
|
+
return (
|
|
330
|
+
RateLimiter(
|
|
331
|
+
rate=self._settings.embedding_rate_limit,
|
|
332
|
+
capacity=int(self._settings.embedding_rate_limit * 2),
|
|
333
|
+
),
|
|
334
|
+
None,
|
|
335
|
+
False,
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
def create_cache(self) -> tuple[ResponseCache | None, bool, float]:
|
|
339
|
+
"""Create response cache based on settings.
|
|
340
|
+
|
|
341
|
+
Returns:
|
|
342
|
+
Tuple of (cache, enabled, regions_ttl).
|
|
343
|
+
"""
|
|
344
|
+
if not self._settings.response_cache_enabled:
|
|
345
|
+
return None, False, 0.0
|
|
346
|
+
return (
|
|
347
|
+
ResponseCache(
|
|
348
|
+
max_size=self._settings.response_cache_max_size,
|
|
349
|
+
default_ttl=self._settings.response_cache_default_ttl,
|
|
350
|
+
),
|
|
351
|
+
True,
|
|
352
|
+
self._settings.response_cache_regions_ttl,
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
def create_decay_manager(
|
|
356
|
+
self,
|
|
357
|
+
repository: MemoryRepositoryProtocol,
|
|
358
|
+
) -> DecayManager | None:
|
|
359
|
+
"""Create the decay manager based on settings.
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
repository: Repository for persisting decay updates.
|
|
363
|
+
|
|
364
|
+
Returns:
|
|
365
|
+
DecayManager if auto-decay is enabled, None otherwise.
|
|
366
|
+
"""
|
|
367
|
+
if not self._settings.auto_decay_enabled:
|
|
368
|
+
return None
|
|
369
|
+
|
|
370
|
+
config = AutoDecayConfig(
|
|
371
|
+
enabled=self._settings.auto_decay_enabled,
|
|
372
|
+
persist_enabled=self._settings.auto_decay_persist_enabled,
|
|
373
|
+
persist_batch_size=self._settings.auto_decay_persist_batch_size,
|
|
374
|
+
persist_flush_interval_seconds=self._settings.auto_decay_persist_flush_interval_seconds,
|
|
375
|
+
min_change_threshold=self._settings.auto_decay_min_change_threshold,
|
|
376
|
+
max_queue_size=self._settings.auto_decay_max_queue_size,
|
|
377
|
+
half_life_days=self._settings.decay_default_half_life_days,
|
|
378
|
+
min_importance_floor=self._settings.decay_min_importance_floor,
|
|
379
|
+
access_weight=0.3, # Default access weight
|
|
380
|
+
decay_function=self._settings.auto_decay_function, # type: ignore[arg-type]
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
return DecayManager(repository=repository, config=config)
|
|
384
|
+
|
|
385
|
+
def create_all(self) -> ServiceContainer:
|
|
386
|
+
"""Create all services with proper dependency wiring.
|
|
387
|
+
|
|
388
|
+
Returns:
|
|
389
|
+
ServiceContainer with all services initialized.
|
|
390
|
+
"""
|
|
391
|
+
# Use injected dependencies or create new ones
|
|
392
|
+
embeddings: EmbeddingServiceProtocol
|
|
393
|
+
if self._injected_embeddings is None:
|
|
394
|
+
embeddings = self.create_embedding_service()
|
|
395
|
+
else:
|
|
396
|
+
embeddings = self._injected_embeddings
|
|
397
|
+
|
|
398
|
+
# Auto-detect embedding dimensions
|
|
399
|
+
embedding_dim = embeddings.dimensions
|
|
400
|
+
logger.info(f"Auto-detected embedding dimensions: {embedding_dim}")
|
|
401
|
+
logger.info(f"Embedding backend: {embeddings.backend}")
|
|
402
|
+
|
|
403
|
+
# Create database and repository
|
|
404
|
+
database: Database | None = None
|
|
405
|
+
repository: MemoryRepositoryProtocol
|
|
406
|
+
if self._injected_repository is None:
|
|
407
|
+
database = self.create_database(embedding_dim)
|
|
408
|
+
repository = self.create_repository(database)
|
|
409
|
+
else:
|
|
410
|
+
repository = self._injected_repository
|
|
411
|
+
|
|
412
|
+
# Create services with shared dependencies
|
|
413
|
+
memory = self.create_memory_service(repository, embeddings)
|
|
414
|
+
spatial = self.create_spatial_service(repository, embeddings)
|
|
415
|
+
lifecycle = self.create_lifecycle_service(repository, embeddings)
|
|
416
|
+
utility = self.create_utility_service(repository, embeddings)
|
|
417
|
+
export_import = self.create_export_import_service(repository, embeddings)
|
|
418
|
+
|
|
419
|
+
# Create decay manager
|
|
420
|
+
decay_manager = self.create_decay_manager(repository)
|
|
421
|
+
|
|
422
|
+
# Create rate limiter
|
|
423
|
+
rate_limiter, agent_rate_limiter, per_agent_enabled = self.create_rate_limiter()
|
|
424
|
+
|
|
425
|
+
# Create cache
|
|
426
|
+
cache, cache_enabled, regions_cache_ttl = self.create_cache()
|
|
427
|
+
|
|
428
|
+
return ServiceContainer(
|
|
429
|
+
embeddings=embeddings,
|
|
430
|
+
database=database,
|
|
431
|
+
repository=repository,
|
|
432
|
+
memory=memory,
|
|
433
|
+
spatial=spatial,
|
|
434
|
+
lifecycle=lifecycle,
|
|
435
|
+
utility=utility,
|
|
436
|
+
export_import=export_import,
|
|
437
|
+
decay_manager=decay_manager,
|
|
438
|
+
rate_limiter=rate_limiter,
|
|
439
|
+
agent_rate_limiter=agent_rate_limiter,
|
|
440
|
+
cache=cache,
|
|
441
|
+
per_agent_rate_limiting=per_agent_enabled,
|
|
442
|
+
cache_enabled=cache_enabled,
|
|
443
|
+
regions_cache_ttl=regions_cache_ttl,
|
|
444
|
+
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Database migrations for spatial-memory-mcp.
|
|
2
|
+
|
|
3
|
+
This package contains database migration scripts for schema changes.
|
|
4
|
+
Each migration is a module that exports a Migration class.
|
|
5
|
+
|
|
6
|
+
Migrations should be numbered sequentially (001, 002, etc.) and use
|
|
7
|
+
semantic versioning for their version string.
|
|
8
|
+
|
|
9
|
+
Example:
|
|
10
|
+
# migrations/001_add_expires_at.py
|
|
11
|
+
from spatial_memory.core.db_migrations import Migration
|
|
12
|
+
|
|
13
|
+
class Migration001AddExpiresAt(Migration):
|
|
14
|
+
version = "1.1.0"
|
|
15
|
+
description = "Add expires_at column for TTL support"
|
|
16
|
+
|
|
17
|
+
def up(self, db, embeddings=None):
|
|
18
|
+
# Apply migration
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
def down(self, db):
|
|
22
|
+
# Rollback migration (optional)
|
|
23
|
+
raise NotImplementedError("Rollback not supported")
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from spatial_memory.core.db_migrations import (
|
|
27
|
+
CURRENT_SCHEMA_VERSION,
|
|
28
|
+
Migration,
|
|
29
|
+
MigrationManager,
|
|
30
|
+
MigrationResult,
|
|
31
|
+
check_migration_status,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
"CURRENT_SCHEMA_VERSION",
|
|
36
|
+
"Migration",
|
|
37
|
+
"MigrationManager",
|
|
38
|
+
"MigrationResult",
|
|
39
|
+
"check_migration_status",
|
|
40
|
+
]
|