alma-memory 0.5.0__py3-none-any.whl → 0.7.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 (111) hide show
  1. alma/__init__.py +296 -194
  2. alma/compression/__init__.py +33 -0
  3. alma/compression/pipeline.py +980 -0
  4. alma/confidence/__init__.py +47 -47
  5. alma/confidence/engine.py +540 -540
  6. alma/confidence/types.py +351 -351
  7. alma/config/loader.py +157 -157
  8. alma/consolidation/__init__.py +23 -23
  9. alma/consolidation/engine.py +678 -678
  10. alma/consolidation/prompts.py +84 -84
  11. alma/core.py +1189 -322
  12. alma/domains/__init__.py +30 -30
  13. alma/domains/factory.py +359 -359
  14. alma/domains/schemas.py +448 -448
  15. alma/domains/types.py +272 -272
  16. alma/events/__init__.py +75 -75
  17. alma/events/emitter.py +285 -284
  18. alma/events/storage_mixin.py +246 -246
  19. alma/events/types.py +126 -126
  20. alma/events/webhook.py +425 -425
  21. alma/exceptions.py +49 -49
  22. alma/extraction/__init__.py +31 -31
  23. alma/extraction/auto_learner.py +265 -264
  24. alma/extraction/extractor.py +420 -420
  25. alma/graph/__init__.py +106 -81
  26. alma/graph/backends/__init__.py +32 -18
  27. alma/graph/backends/kuzu.py +624 -0
  28. alma/graph/backends/memgraph.py +432 -0
  29. alma/graph/backends/memory.py +236 -236
  30. alma/graph/backends/neo4j.py +417 -417
  31. alma/graph/base.py +159 -159
  32. alma/graph/extraction.py +198 -198
  33. alma/graph/store.py +860 -860
  34. alma/harness/__init__.py +35 -35
  35. alma/harness/base.py +386 -386
  36. alma/harness/domains.py +705 -705
  37. alma/initializer/__init__.py +37 -37
  38. alma/initializer/initializer.py +418 -418
  39. alma/initializer/types.py +250 -250
  40. alma/integration/__init__.py +62 -62
  41. alma/integration/claude_agents.py +444 -432
  42. alma/integration/helena.py +423 -423
  43. alma/integration/victor.py +471 -471
  44. alma/learning/__init__.py +101 -86
  45. alma/learning/decay.py +878 -0
  46. alma/learning/forgetting.py +1446 -1446
  47. alma/learning/heuristic_extractor.py +390 -390
  48. alma/learning/protocols.py +374 -374
  49. alma/learning/validation.py +346 -346
  50. alma/mcp/__init__.py +123 -45
  51. alma/mcp/__main__.py +156 -156
  52. alma/mcp/resources.py +122 -122
  53. alma/mcp/server.py +955 -591
  54. alma/mcp/tools.py +3254 -511
  55. alma/observability/__init__.py +91 -0
  56. alma/observability/config.py +302 -0
  57. alma/observability/guidelines.py +170 -0
  58. alma/observability/logging.py +424 -0
  59. alma/observability/metrics.py +583 -0
  60. alma/observability/tracing.py +440 -0
  61. alma/progress/__init__.py +21 -21
  62. alma/progress/tracker.py +607 -607
  63. alma/progress/types.py +250 -250
  64. alma/retrieval/__init__.py +134 -53
  65. alma/retrieval/budget.py +525 -0
  66. alma/retrieval/cache.py +1304 -1061
  67. alma/retrieval/embeddings.py +202 -202
  68. alma/retrieval/engine.py +850 -366
  69. alma/retrieval/modes.py +365 -0
  70. alma/retrieval/progressive.py +560 -0
  71. alma/retrieval/scoring.py +344 -344
  72. alma/retrieval/trust_scoring.py +637 -0
  73. alma/retrieval/verification.py +797 -0
  74. alma/session/__init__.py +19 -19
  75. alma/session/manager.py +442 -399
  76. alma/session/types.py +288 -288
  77. alma/storage/__init__.py +101 -61
  78. alma/storage/archive.py +233 -0
  79. alma/storage/azure_cosmos.py +1259 -1048
  80. alma/storage/base.py +1083 -525
  81. alma/storage/chroma.py +1443 -1443
  82. alma/storage/constants.py +103 -0
  83. alma/storage/file_based.py +614 -619
  84. alma/storage/migrations/__init__.py +21 -0
  85. alma/storage/migrations/base.py +321 -0
  86. alma/storage/migrations/runner.py +323 -0
  87. alma/storage/migrations/version_stores.py +337 -0
  88. alma/storage/migrations/versions/__init__.py +11 -0
  89. alma/storage/migrations/versions/v1_0_0.py +373 -0
  90. alma/storage/migrations/versions/v1_1_0_workflow_context.py +551 -0
  91. alma/storage/pinecone.py +1080 -1080
  92. alma/storage/postgresql.py +1948 -1452
  93. alma/storage/qdrant.py +1306 -1306
  94. alma/storage/sqlite_local.py +3041 -1358
  95. alma/testing/__init__.py +46 -0
  96. alma/testing/factories.py +301 -0
  97. alma/testing/mocks.py +389 -0
  98. alma/types.py +292 -264
  99. alma/utils/__init__.py +19 -0
  100. alma/utils/tokenizer.py +521 -0
  101. alma/workflow/__init__.py +83 -0
  102. alma/workflow/artifacts.py +170 -0
  103. alma/workflow/checkpoint.py +311 -0
  104. alma/workflow/context.py +228 -0
  105. alma/workflow/outcomes.py +189 -0
  106. alma/workflow/reducers.py +393 -0
  107. {alma_memory-0.5.0.dist-info → alma_memory-0.7.0.dist-info}/METADATA +244 -72
  108. alma_memory-0.7.0.dist-info/RECORD +112 -0
  109. alma_memory-0.5.0.dist-info/RECORD +0 -76
  110. {alma_memory-0.5.0.dist-info → alma_memory-0.7.0.dist-info}/WHEEL +0 -0
  111. {alma_memory-0.5.0.dist-info → alma_memory-0.7.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,337 @@
1
+ """
2
+ ALMA Migration Framework - Version Stores.
3
+
4
+ Implementations of version tracking for different storage backends.
5
+ """
6
+
7
+ import json
8
+ import logging
9
+ import sqlite3
10
+ from contextlib import contextmanager
11
+ from datetime import datetime
12
+ from pathlib import Path
13
+ from typing import Any, List, Optional
14
+
15
+ from alma.storage.migrations.base import SchemaVersion
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class SQLiteVersionStore:
21
+ """
22
+ Version store using SQLite for tracking schema versions.
23
+
24
+ Creates a `_schema_versions` table to track applied migrations.
25
+ """
26
+
27
+ def __init__(self, db_path: Path):
28
+ """
29
+ Initialize SQLite version store.
30
+
31
+ Args:
32
+ db_path: Path to SQLite database file
33
+ """
34
+ self.db_path = Path(db_path)
35
+ self._init_version_table()
36
+
37
+ @contextmanager
38
+ def _get_connection(self):
39
+ """Get database connection with context manager."""
40
+ conn = sqlite3.connect(self.db_path)
41
+ conn.row_factory = sqlite3.Row
42
+ try:
43
+ yield conn
44
+ conn.commit()
45
+ except Exception:
46
+ conn.rollback()
47
+ raise
48
+ finally:
49
+ conn.close()
50
+
51
+ def _init_version_table(self) -> None:
52
+ """Create schema versions table if it doesn't exist."""
53
+ with self._get_connection() as conn:
54
+ cursor = conn.cursor()
55
+ cursor.execute("""
56
+ CREATE TABLE IF NOT EXISTS _schema_versions (
57
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
58
+ version TEXT NOT NULL UNIQUE,
59
+ applied_at TEXT NOT NULL,
60
+ description TEXT,
61
+ checksum TEXT
62
+ )
63
+ """)
64
+ cursor.execute(
65
+ "CREATE INDEX IF NOT EXISTS idx_schema_version "
66
+ "ON _schema_versions(version)"
67
+ )
68
+
69
+ def get_current_version(self) -> Optional[str]:
70
+ """Get the current (latest) schema version."""
71
+ with self._get_connection() as conn:
72
+ cursor = conn.cursor()
73
+ cursor.execute("""
74
+ SELECT version FROM _schema_versions
75
+ ORDER BY id DESC LIMIT 1
76
+ """)
77
+ row = cursor.fetchone()
78
+ return row["version"] if row else None
79
+
80
+ def get_version_history(self) -> List[SchemaVersion]:
81
+ """Get all applied versions in chronological order."""
82
+ with self._get_connection() as conn:
83
+ cursor = conn.cursor()
84
+ cursor.execute("""
85
+ SELECT version, applied_at, description, checksum
86
+ FROM _schema_versions
87
+ ORDER BY id ASC
88
+ """)
89
+ rows = cursor.fetchall()
90
+
91
+ return [
92
+ SchemaVersion(
93
+ version=row["version"],
94
+ applied_at=datetime.fromisoformat(row["applied_at"]),
95
+ description=row["description"] or "",
96
+ checksum=row["checksum"],
97
+ )
98
+ for row in rows
99
+ ]
100
+
101
+ def record_version(self, version: SchemaVersion) -> None:
102
+ """Record a new schema version."""
103
+ with self._get_connection() as conn:
104
+ cursor = conn.cursor()
105
+ cursor.execute(
106
+ """
107
+ INSERT INTO _schema_versions (version, applied_at, description, checksum)
108
+ VALUES (?, ?, ?, ?)
109
+ """,
110
+ (
111
+ version.version,
112
+ version.applied_at.isoformat(),
113
+ version.description,
114
+ version.checksum,
115
+ ),
116
+ )
117
+ logger.debug(f"Recorded schema version {version.version}")
118
+
119
+ def remove_version(self, version: str) -> None:
120
+ """Remove a version record (for rollback)."""
121
+ with self._get_connection() as conn:
122
+ cursor = conn.cursor()
123
+ cursor.execute(
124
+ "DELETE FROM _schema_versions WHERE version = ?",
125
+ (version,),
126
+ )
127
+ logger.debug(f"Removed schema version {version}")
128
+
129
+ def has_version_table(self) -> bool:
130
+ """Check if the version table exists."""
131
+ with self._get_connection() as conn:
132
+ cursor = conn.cursor()
133
+ cursor.execute("""
134
+ SELECT name FROM sqlite_master
135
+ WHERE type='table' AND name='_schema_versions'
136
+ """)
137
+ return cursor.fetchone() is not None
138
+
139
+
140
+ class PostgreSQLVersionStore:
141
+ """
142
+ Version store using PostgreSQL for tracking schema versions.
143
+
144
+ Creates an `_schema_versions` table in the configured schema.
145
+ """
146
+
147
+ def __init__(self, pool: Any, schema: str = "public"):
148
+ """
149
+ Initialize PostgreSQL version store.
150
+
151
+ Args:
152
+ pool: psycopg connection pool
153
+ schema: Database schema name
154
+ """
155
+ self._pool = pool
156
+ self.schema = schema
157
+ self._init_version_table()
158
+
159
+ @contextmanager
160
+ def _get_connection(self):
161
+ """Get database connection from pool."""
162
+ with self._pool.connection() as conn:
163
+ yield conn
164
+
165
+ def _init_version_table(self) -> None:
166
+ """Create schema versions table if it doesn't exist."""
167
+ with self._get_connection() as conn:
168
+ conn.execute(f"""
169
+ CREATE TABLE IF NOT EXISTS {self.schema}._schema_versions (
170
+ id SERIAL PRIMARY KEY,
171
+ version TEXT NOT NULL UNIQUE,
172
+ applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
173
+ description TEXT,
174
+ checksum TEXT
175
+ )
176
+ """)
177
+ conn.execute(f"""
178
+ CREATE INDEX IF NOT EXISTS idx_schema_version
179
+ ON {self.schema}._schema_versions(version)
180
+ """)
181
+ conn.commit()
182
+
183
+ def get_current_version(self) -> Optional[str]:
184
+ """Get the current (latest) schema version."""
185
+ with self._get_connection() as conn:
186
+ cursor = conn.execute(f"""
187
+ SELECT version FROM {self.schema}._schema_versions
188
+ ORDER BY id DESC LIMIT 1
189
+ """)
190
+ row = cursor.fetchone()
191
+ return row["version"] if row else None
192
+
193
+ def get_version_history(self) -> List[SchemaVersion]:
194
+ """Get all applied versions in chronological order."""
195
+ with self._get_connection() as conn:
196
+ cursor = conn.execute(f"""
197
+ SELECT version, applied_at, description, checksum
198
+ FROM {self.schema}._schema_versions
199
+ ORDER BY id ASC
200
+ """)
201
+ rows = cursor.fetchall()
202
+
203
+ return [
204
+ SchemaVersion(
205
+ version=row["version"],
206
+ applied_at=row["applied_at"]
207
+ if isinstance(row["applied_at"], datetime)
208
+ else datetime.fromisoformat(str(row["applied_at"])),
209
+ description=row["description"] or "",
210
+ checksum=row["checksum"],
211
+ )
212
+ for row in rows
213
+ ]
214
+
215
+ def record_version(self, version: SchemaVersion) -> None:
216
+ """Record a new schema version."""
217
+ with self._get_connection() as conn:
218
+ conn.execute(
219
+ f"""
220
+ INSERT INTO {self.schema}._schema_versions
221
+ (version, applied_at, description, checksum)
222
+ VALUES (%s, %s, %s, %s)
223
+ """,
224
+ (
225
+ version.version,
226
+ version.applied_at,
227
+ version.description,
228
+ version.checksum,
229
+ ),
230
+ )
231
+ conn.commit()
232
+ logger.debug(f"Recorded schema version {version.version}")
233
+
234
+ def remove_version(self, version: str) -> None:
235
+ """Remove a version record (for rollback)."""
236
+ with self._get_connection() as conn:
237
+ conn.execute(
238
+ f"DELETE FROM {self.schema}._schema_versions WHERE version = %s",
239
+ (version,),
240
+ )
241
+ conn.commit()
242
+ logger.debug(f"Removed schema version {version}")
243
+
244
+ def has_version_table(self) -> bool:
245
+ """Check if the version table exists."""
246
+ with self._get_connection() as conn:
247
+ cursor = conn.execute(
248
+ """
249
+ SELECT EXISTS (
250
+ SELECT FROM information_schema.tables
251
+ WHERE table_schema = %s
252
+ AND table_name = '_schema_versions'
253
+ )
254
+ """,
255
+ (self.schema,),
256
+ )
257
+ row = cursor.fetchone()
258
+ return row["exists"] if row else False
259
+
260
+
261
+ class FileBasedVersionStore:
262
+ """
263
+ Version store using a JSON file for tracking schema versions.
264
+
265
+ Useful for file-based storage backends.
266
+ """
267
+
268
+ def __init__(self, storage_dir: Path):
269
+ """
270
+ Initialize file-based version store.
271
+
272
+ Args:
273
+ storage_dir: Directory to store version file
274
+ """
275
+ self.storage_dir = Path(storage_dir)
276
+ self.version_file = self.storage_dir / "_schema_versions.json"
277
+ self._ensure_file_exists()
278
+
279
+ def _ensure_file_exists(self) -> None:
280
+ """Create version file if it doesn't exist."""
281
+ self.storage_dir.mkdir(parents=True, exist_ok=True)
282
+ if not self.version_file.exists():
283
+ self._write_versions([])
284
+
285
+ def _read_versions(self) -> List[dict]:
286
+ """Read versions from file."""
287
+ try:
288
+ with open(self.version_file, "r") as f:
289
+ return json.load(f)
290
+ except (json.JSONDecodeError, FileNotFoundError):
291
+ return []
292
+
293
+ def _write_versions(self, versions: List[dict]) -> None:
294
+ """Write versions to file."""
295
+ with open(self.version_file, "w") as f:
296
+ json.dump(versions, f, indent=2, default=str)
297
+
298
+ def get_current_version(self) -> Optional[str]:
299
+ """Get the current (latest) schema version."""
300
+ versions = self._read_versions()
301
+ if not versions:
302
+ return None
303
+ return versions[-1]["version"]
304
+
305
+ def get_version_history(self) -> List[SchemaVersion]:
306
+ """Get all applied versions in chronological order."""
307
+ versions = self._read_versions()
308
+ return [
309
+ SchemaVersion(
310
+ version=v["version"],
311
+ applied_at=datetime.fromisoformat(v["applied_at"]),
312
+ description=v.get("description", ""),
313
+ checksum=v.get("checksum"),
314
+ )
315
+ for v in versions
316
+ ]
317
+
318
+ def record_version(self, version: SchemaVersion) -> None:
319
+ """Record a new schema version."""
320
+ versions = self._read_versions()
321
+ versions.append(
322
+ {
323
+ "version": version.version,
324
+ "applied_at": version.applied_at.isoformat(),
325
+ "description": version.description,
326
+ "checksum": version.checksum,
327
+ }
328
+ )
329
+ self._write_versions(versions)
330
+ logger.debug(f"Recorded schema version {version.version}")
331
+
332
+ def remove_version(self, version: str) -> None:
333
+ """Remove a version record (for rollback)."""
334
+ versions = self._read_versions()
335
+ versions = [v for v in versions if v["version"] != version]
336
+ self._write_versions(versions)
337
+ logger.debug(f"Removed schema version {version}")
@@ -0,0 +1,11 @@
1
+ """
2
+ ALMA Schema Migrations - Version Definitions.
3
+
4
+ Each version file contains migrations for that schema version.
5
+ Migrations are automatically registered when imported.
6
+ """
7
+
8
+ # Import all version modules to register migrations
9
+ from alma.storage.migrations.versions import v1_0_0, v1_1_0_workflow_context
10
+
11
+ __all__ = ["v1_0_0", "v1_1_0_workflow_context"]