alma-memory 0.2.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.
- alma/__init__.py +75 -0
- alma/config/__init__.py +5 -0
- alma/config/loader.py +156 -0
- alma/core.py +322 -0
- alma/harness/__init__.py +35 -0
- alma/harness/base.py +377 -0
- alma/harness/domains.py +689 -0
- alma/integration/__init__.py +62 -0
- alma/integration/claude_agents.py +432 -0
- alma/integration/helena.py +413 -0
- alma/integration/victor.py +447 -0
- alma/learning/__init__.py +86 -0
- alma/learning/forgetting.py +1396 -0
- alma/learning/heuristic_extractor.py +374 -0
- alma/learning/protocols.py +326 -0
- alma/learning/validation.py +341 -0
- alma/mcp/__init__.py +45 -0
- alma/mcp/__main__.py +155 -0
- alma/mcp/resources.py +121 -0
- alma/mcp/server.py +533 -0
- alma/mcp/tools.py +374 -0
- alma/retrieval/__init__.py +53 -0
- alma/retrieval/cache.py +1062 -0
- alma/retrieval/embeddings.py +202 -0
- alma/retrieval/engine.py +287 -0
- alma/retrieval/scoring.py +334 -0
- alma/storage/__init__.py +20 -0
- alma/storage/azure_cosmos.py +972 -0
- alma/storage/base.py +372 -0
- alma/storage/file_based.py +583 -0
- alma/storage/sqlite_local.py +912 -0
- alma/types.py +216 -0
- alma_memory-0.2.0.dist-info/METADATA +327 -0
- alma_memory-0.2.0.dist-info/RECORD +36 -0
- alma_memory-0.2.0.dist-info/WHEEL +5 -0
- alma_memory-0.2.0.dist-info/top_level.txt +1 -0
alma/storage/base.py
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ALMA Storage Backend Interface.
|
|
3
|
+
|
|
4
|
+
Abstract base class that all storage backends must implement.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from abc import ABC, abstractmethod
|
|
8
|
+
from typing import Optional, List, Dict, Any
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
|
|
11
|
+
from alma.types import (
|
|
12
|
+
Heuristic,
|
|
13
|
+
Outcome,
|
|
14
|
+
UserPreference,
|
|
15
|
+
DomainKnowledge,
|
|
16
|
+
AntiPattern,
|
|
17
|
+
MemoryType,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class StorageBackend(ABC):
|
|
22
|
+
"""
|
|
23
|
+
Abstract base class for ALMA storage backends.
|
|
24
|
+
|
|
25
|
+
Implementations:
|
|
26
|
+
- FileBasedStorage: JSON files (testing/fallback)
|
|
27
|
+
- SQLiteStorage: Local SQLite + FAISS vectors
|
|
28
|
+
- AzureCosmosStorage: Production Azure Cosmos DB
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
# ==================== WRITE OPERATIONS ====================
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
def save_heuristic(self, heuristic: Heuristic) -> str:
|
|
35
|
+
"""Save a heuristic, return its ID."""
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
@abstractmethod
|
|
39
|
+
def save_outcome(self, outcome: Outcome) -> str:
|
|
40
|
+
"""Save an outcome, return its ID."""
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
@abstractmethod
|
|
44
|
+
def save_user_preference(self, preference: UserPreference) -> str:
|
|
45
|
+
"""Save a user preference, return its ID."""
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
@abstractmethod
|
|
49
|
+
def save_domain_knowledge(self, knowledge: DomainKnowledge) -> str:
|
|
50
|
+
"""Save domain knowledge, return its ID."""
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def save_anti_pattern(self, anti_pattern: AntiPattern) -> str:
|
|
55
|
+
"""Save an anti-pattern, return its ID."""
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
# ==================== READ OPERATIONS ====================
|
|
59
|
+
|
|
60
|
+
@abstractmethod
|
|
61
|
+
def get_heuristics(
|
|
62
|
+
self,
|
|
63
|
+
project_id: str,
|
|
64
|
+
agent: Optional[str] = None,
|
|
65
|
+
embedding: Optional[List[float]] = None,
|
|
66
|
+
top_k: int = 5,
|
|
67
|
+
min_confidence: float = 0.0,
|
|
68
|
+
) -> List[Heuristic]:
|
|
69
|
+
"""
|
|
70
|
+
Get heuristics, optionally filtered by agent and similarity.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
project_id: Project to query
|
|
74
|
+
agent: Filter by agent name
|
|
75
|
+
embedding: Query embedding for semantic search
|
|
76
|
+
top_k: Max results to return
|
|
77
|
+
min_confidence: Minimum confidence threshold
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
List of matching heuristics
|
|
81
|
+
"""
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
@abstractmethod
|
|
85
|
+
def get_outcomes(
|
|
86
|
+
self,
|
|
87
|
+
project_id: str,
|
|
88
|
+
agent: Optional[str] = None,
|
|
89
|
+
task_type: Optional[str] = None,
|
|
90
|
+
embedding: Optional[List[float]] = None,
|
|
91
|
+
top_k: int = 5,
|
|
92
|
+
success_only: bool = False,
|
|
93
|
+
) -> List[Outcome]:
|
|
94
|
+
"""
|
|
95
|
+
Get outcomes, optionally filtered.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
project_id: Project to query
|
|
99
|
+
agent: Filter by agent name
|
|
100
|
+
task_type: Filter by task type
|
|
101
|
+
embedding: Query embedding for semantic search
|
|
102
|
+
top_k: Max results
|
|
103
|
+
success_only: Only return successful outcomes
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
List of matching outcomes
|
|
107
|
+
"""
|
|
108
|
+
pass
|
|
109
|
+
|
|
110
|
+
@abstractmethod
|
|
111
|
+
def get_user_preferences(
|
|
112
|
+
self,
|
|
113
|
+
user_id: str,
|
|
114
|
+
category: Optional[str] = None,
|
|
115
|
+
) -> List[UserPreference]:
|
|
116
|
+
"""
|
|
117
|
+
Get user preferences.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
user_id: User to query
|
|
121
|
+
category: Optional category filter
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
List of user preferences
|
|
125
|
+
"""
|
|
126
|
+
pass
|
|
127
|
+
|
|
128
|
+
@abstractmethod
|
|
129
|
+
def get_domain_knowledge(
|
|
130
|
+
self,
|
|
131
|
+
project_id: str,
|
|
132
|
+
agent: Optional[str] = None,
|
|
133
|
+
domain: Optional[str] = None,
|
|
134
|
+
embedding: Optional[List[float]] = None,
|
|
135
|
+
top_k: int = 5,
|
|
136
|
+
) -> List[DomainKnowledge]:
|
|
137
|
+
"""
|
|
138
|
+
Get domain knowledge.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
project_id: Project to query
|
|
142
|
+
agent: Filter by agent
|
|
143
|
+
domain: Filter by domain
|
|
144
|
+
embedding: Query embedding for semantic search
|
|
145
|
+
top_k: Max results
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
List of domain knowledge items
|
|
149
|
+
"""
|
|
150
|
+
pass
|
|
151
|
+
|
|
152
|
+
@abstractmethod
|
|
153
|
+
def get_anti_patterns(
|
|
154
|
+
self,
|
|
155
|
+
project_id: str,
|
|
156
|
+
agent: Optional[str] = None,
|
|
157
|
+
embedding: Optional[List[float]] = None,
|
|
158
|
+
top_k: int = 5,
|
|
159
|
+
) -> List[AntiPattern]:
|
|
160
|
+
"""
|
|
161
|
+
Get anti-patterns.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
project_id: Project to query
|
|
165
|
+
agent: Filter by agent
|
|
166
|
+
embedding: Query embedding for semantic search
|
|
167
|
+
top_k: Max results
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
List of anti-patterns
|
|
171
|
+
"""
|
|
172
|
+
pass
|
|
173
|
+
|
|
174
|
+
# ==================== UPDATE OPERATIONS ====================
|
|
175
|
+
|
|
176
|
+
@abstractmethod
|
|
177
|
+
def update_heuristic(
|
|
178
|
+
self,
|
|
179
|
+
heuristic_id: str,
|
|
180
|
+
updates: Dict[str, Any],
|
|
181
|
+
) -> bool:
|
|
182
|
+
"""
|
|
183
|
+
Update a heuristic's fields.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
heuristic_id: ID of heuristic to update
|
|
187
|
+
updates: Dict of field->value updates
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
True if updated, False if not found
|
|
191
|
+
"""
|
|
192
|
+
pass
|
|
193
|
+
|
|
194
|
+
@abstractmethod
|
|
195
|
+
def increment_heuristic_occurrence(
|
|
196
|
+
self,
|
|
197
|
+
heuristic_id: str,
|
|
198
|
+
success: bool,
|
|
199
|
+
) -> bool:
|
|
200
|
+
"""
|
|
201
|
+
Increment heuristic occurrence count.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
heuristic_id: ID of heuristic
|
|
205
|
+
success: Whether this occurrence was successful
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
True if updated
|
|
209
|
+
"""
|
|
210
|
+
pass
|
|
211
|
+
|
|
212
|
+
@abstractmethod
|
|
213
|
+
def update_heuristic_confidence(
|
|
214
|
+
self,
|
|
215
|
+
heuristic_id: str,
|
|
216
|
+
new_confidence: float,
|
|
217
|
+
) -> bool:
|
|
218
|
+
"""
|
|
219
|
+
Update a heuristic's confidence value.
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
heuristic_id: ID of heuristic to update
|
|
223
|
+
new_confidence: New confidence value (0.0 - 1.0)
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
True if updated, False if not found
|
|
227
|
+
"""
|
|
228
|
+
pass
|
|
229
|
+
|
|
230
|
+
@abstractmethod
|
|
231
|
+
def update_knowledge_confidence(
|
|
232
|
+
self,
|
|
233
|
+
knowledge_id: str,
|
|
234
|
+
new_confidence: float,
|
|
235
|
+
) -> bool:
|
|
236
|
+
"""
|
|
237
|
+
Update domain knowledge confidence value.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
knowledge_id: ID of knowledge to update
|
|
241
|
+
new_confidence: New confidence value (0.0 - 1.0)
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
True if updated, False if not found
|
|
245
|
+
"""
|
|
246
|
+
pass
|
|
247
|
+
|
|
248
|
+
# ==================== DELETE OPERATIONS ====================
|
|
249
|
+
|
|
250
|
+
@abstractmethod
|
|
251
|
+
def delete_heuristic(self, heuristic_id: str) -> bool:
|
|
252
|
+
"""
|
|
253
|
+
Delete a heuristic by ID.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
heuristic_id: ID of heuristic to delete
|
|
257
|
+
|
|
258
|
+
Returns:
|
|
259
|
+
True if deleted, False if not found
|
|
260
|
+
"""
|
|
261
|
+
pass
|
|
262
|
+
|
|
263
|
+
@abstractmethod
|
|
264
|
+
def delete_outcome(self, outcome_id: str) -> bool:
|
|
265
|
+
"""
|
|
266
|
+
Delete an outcome by ID.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
outcome_id: ID of outcome to delete
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
True if deleted, False if not found
|
|
273
|
+
"""
|
|
274
|
+
pass
|
|
275
|
+
|
|
276
|
+
@abstractmethod
|
|
277
|
+
def delete_domain_knowledge(self, knowledge_id: str) -> bool:
|
|
278
|
+
"""
|
|
279
|
+
Delete domain knowledge by ID.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
knowledge_id: ID of knowledge to delete
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
True if deleted, False if not found
|
|
286
|
+
"""
|
|
287
|
+
pass
|
|
288
|
+
|
|
289
|
+
@abstractmethod
|
|
290
|
+
def delete_anti_pattern(self, anti_pattern_id: str) -> bool:
|
|
291
|
+
"""
|
|
292
|
+
Delete an anti-pattern by ID.
|
|
293
|
+
|
|
294
|
+
Args:
|
|
295
|
+
anti_pattern_id: ID of anti-pattern to delete
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
True if deleted, False if not found
|
|
299
|
+
"""
|
|
300
|
+
pass
|
|
301
|
+
|
|
302
|
+
@abstractmethod
|
|
303
|
+
def delete_outcomes_older_than(
|
|
304
|
+
self,
|
|
305
|
+
project_id: str,
|
|
306
|
+
older_than: datetime,
|
|
307
|
+
agent: Optional[str] = None,
|
|
308
|
+
) -> int:
|
|
309
|
+
"""
|
|
310
|
+
Delete old outcomes.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
project_id: Project to prune
|
|
314
|
+
older_than: Delete outcomes older than this
|
|
315
|
+
agent: Optional agent filter
|
|
316
|
+
|
|
317
|
+
Returns:
|
|
318
|
+
Number of items deleted
|
|
319
|
+
"""
|
|
320
|
+
pass
|
|
321
|
+
|
|
322
|
+
@abstractmethod
|
|
323
|
+
def delete_low_confidence_heuristics(
|
|
324
|
+
self,
|
|
325
|
+
project_id: str,
|
|
326
|
+
below_confidence: float,
|
|
327
|
+
agent: Optional[str] = None,
|
|
328
|
+
) -> int:
|
|
329
|
+
"""
|
|
330
|
+
Delete low-confidence heuristics.
|
|
331
|
+
|
|
332
|
+
Args:
|
|
333
|
+
project_id: Project to prune
|
|
334
|
+
below_confidence: Delete below this threshold
|
|
335
|
+
agent: Optional agent filter
|
|
336
|
+
|
|
337
|
+
Returns:
|
|
338
|
+
Number of items deleted
|
|
339
|
+
"""
|
|
340
|
+
pass
|
|
341
|
+
|
|
342
|
+
# ==================== STATS ====================
|
|
343
|
+
|
|
344
|
+
@abstractmethod
|
|
345
|
+
def get_stats(
|
|
346
|
+
self,
|
|
347
|
+
project_id: str,
|
|
348
|
+
agent: Optional[str] = None,
|
|
349
|
+
) -> Dict[str, Any]:
|
|
350
|
+
"""
|
|
351
|
+
Get memory statistics.
|
|
352
|
+
|
|
353
|
+
Returns:
|
|
354
|
+
Dict with counts per memory type, total size, etc.
|
|
355
|
+
"""
|
|
356
|
+
pass
|
|
357
|
+
|
|
358
|
+
# ==================== UTILITY ====================
|
|
359
|
+
|
|
360
|
+
@classmethod
|
|
361
|
+
@abstractmethod
|
|
362
|
+
def from_config(cls, config: Dict[str, Any]) -> "StorageBackend":
|
|
363
|
+
"""
|
|
364
|
+
Create instance from configuration dict.
|
|
365
|
+
|
|
366
|
+
Args:
|
|
367
|
+
config: Configuration dictionary
|
|
368
|
+
|
|
369
|
+
Returns:
|
|
370
|
+
Configured storage backend instance
|
|
371
|
+
"""
|
|
372
|
+
pass
|