alma-memory 0.4.0__py3-none-any.whl → 0.5.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 +88 -44
- alma/confidence/__init__.py +1 -1
- alma/confidence/engine.py +92 -58
- alma/confidence/types.py +34 -14
- alma/config/loader.py +3 -2
- alma/consolidation/__init__.py +23 -0
- alma/consolidation/engine.py +678 -0
- alma/consolidation/prompts.py +84 -0
- alma/core.py +15 -15
- alma/domains/__init__.py +6 -6
- alma/domains/factory.py +12 -9
- alma/domains/schemas.py +17 -3
- alma/domains/types.py +8 -4
- alma/events/__init__.py +75 -0
- alma/events/emitter.py +284 -0
- alma/events/storage_mixin.py +246 -0
- alma/events/types.py +126 -0
- alma/events/webhook.py +425 -0
- alma/exceptions.py +49 -0
- alma/extraction/__init__.py +31 -0
- alma/extraction/auto_learner.py +264 -0
- alma/extraction/extractor.py +420 -0
- alma/graph/__init__.py +81 -0
- alma/graph/backends/__init__.py +18 -0
- alma/graph/backends/memory.py +236 -0
- alma/graph/backends/neo4j.py +417 -0
- alma/graph/base.py +159 -0
- alma/graph/extraction.py +198 -0
- alma/graph/store.py +860 -0
- alma/harness/__init__.py +4 -4
- alma/harness/base.py +18 -9
- alma/harness/domains.py +27 -11
- alma/initializer/__init__.py +1 -1
- alma/initializer/initializer.py +51 -43
- alma/initializer/types.py +25 -17
- alma/integration/__init__.py +9 -9
- alma/integration/claude_agents.py +10 -10
- alma/integration/helena.py +32 -22
- alma/integration/victor.py +57 -33
- alma/learning/__init__.py +27 -27
- alma/learning/forgetting.py +198 -148
- alma/learning/heuristic_extractor.py +40 -24
- alma/learning/protocols.py +62 -14
- alma/learning/validation.py +7 -2
- alma/mcp/__init__.py +4 -4
- alma/mcp/__main__.py +2 -1
- alma/mcp/resources.py +17 -16
- alma/mcp/server.py +102 -44
- alma/mcp/tools.py +174 -37
- alma/progress/__init__.py +3 -3
- alma/progress/tracker.py +26 -20
- alma/progress/types.py +8 -12
- alma/py.typed +0 -0
- alma/retrieval/__init__.py +11 -11
- alma/retrieval/cache.py +20 -21
- alma/retrieval/embeddings.py +4 -4
- alma/retrieval/engine.py +114 -35
- alma/retrieval/scoring.py +73 -63
- alma/session/__init__.py +2 -2
- alma/session/manager.py +5 -5
- alma/session/types.py +5 -4
- alma/storage/__init__.py +41 -0
- alma/storage/azure_cosmos.py +101 -31
- alma/storage/base.py +157 -4
- alma/storage/chroma.py +1443 -0
- alma/storage/file_based.py +56 -20
- alma/storage/pinecone.py +1080 -0
- alma/storage/postgresql.py +1452 -0
- alma/storage/qdrant.py +1306 -0
- alma/storage/sqlite_local.py +376 -31
- alma/types.py +62 -14
- alma_memory-0.5.0.dist-info/METADATA +905 -0
- alma_memory-0.5.0.dist-info/RECORD +76 -0
- {alma_memory-0.4.0.dist-info → alma_memory-0.5.0.dist-info}/WHEEL +1 -1
- alma_memory-0.4.0.dist-info/METADATA +0 -488
- alma_memory-0.4.0.dist-info/RECORD +0 -52
- {alma_memory-0.4.0.dist-info → alma_memory-0.5.0.dist-info}/top_level.txt +0 -0
alma/types.py
CHANGED
|
@@ -5,13 +5,14 @@ Defines the core data structures for all memory types.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from dataclasses import dataclass, field
|
|
8
|
-
from datetime import datetime
|
|
9
|
-
from typing import Optional, List, Dict, Any
|
|
8
|
+
from datetime import datetime, timezone
|
|
10
9
|
from enum import Enum
|
|
10
|
+
from typing import Any, Dict, List, Optional
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class MemoryType(Enum):
|
|
14
14
|
"""Categories of memory that agents can store and retrieve."""
|
|
15
|
+
|
|
15
16
|
HEURISTIC = "heuristic"
|
|
16
17
|
OUTCOME = "outcome"
|
|
17
18
|
USER_PREFERENCE = "user_preference"
|
|
@@ -22,13 +23,21 @@ class MemoryType(Enum):
|
|
|
22
23
|
@dataclass
|
|
23
24
|
class MemoryScope:
|
|
24
25
|
"""
|
|
25
|
-
Defines what an agent is allowed to learn.
|
|
26
|
+
Defines what an agent is allowed to learn and share.
|
|
26
27
|
|
|
27
28
|
Prevents scope creep by explicitly listing allowed and forbidden domains.
|
|
29
|
+
Supports multi-agent memory sharing through share_with and inherit_from.
|
|
28
30
|
"""
|
|
31
|
+
|
|
29
32
|
agent_name: str
|
|
30
33
|
can_learn: List[str]
|
|
31
34
|
cannot_learn: List[str]
|
|
35
|
+
share_with: List[str] = field(
|
|
36
|
+
default_factory=list
|
|
37
|
+
) # Agents that can read this agent's memories
|
|
38
|
+
inherit_from: List[str] = field(
|
|
39
|
+
default_factory=list
|
|
40
|
+
) # Agents whose memories this agent can read
|
|
32
41
|
min_occurrences_for_heuristic: int = 3
|
|
33
42
|
|
|
34
43
|
def is_allowed(self, domain: str) -> bool:
|
|
@@ -39,6 +48,39 @@ class MemoryScope:
|
|
|
39
48
|
return True
|
|
40
49
|
return domain in self.can_learn
|
|
41
50
|
|
|
51
|
+
def get_readable_agents(self) -> List[str]:
|
|
52
|
+
"""
|
|
53
|
+
Get list of agents whose memories this agent can read.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
List containing this agent's name plus all inherited agents.
|
|
57
|
+
"""
|
|
58
|
+
return [self.agent_name] + list(self.inherit_from)
|
|
59
|
+
|
|
60
|
+
def can_read_from(self, other_agent: str) -> bool:
|
|
61
|
+
"""
|
|
62
|
+
Check if this agent can read memories from another agent.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
other_agent: Name of the agent to check
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
True if this agent can read from other_agent
|
|
69
|
+
"""
|
|
70
|
+
return other_agent == self.agent_name or other_agent in self.inherit_from
|
|
71
|
+
|
|
72
|
+
def shares_with(self, other_agent: str) -> bool:
|
|
73
|
+
"""
|
|
74
|
+
Check if this agent shares memories with another agent.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
other_agent: Name of the agent to check
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
True if this agent shares with other_agent
|
|
81
|
+
"""
|
|
82
|
+
return other_agent in self.share_with
|
|
83
|
+
|
|
42
84
|
|
|
43
85
|
@dataclass
|
|
44
86
|
class Heuristic:
|
|
@@ -47,11 +89,12 @@ class Heuristic:
|
|
|
47
89
|
|
|
48
90
|
Heuristics are only created after min_occurrences validations.
|
|
49
91
|
"""
|
|
92
|
+
|
|
50
93
|
id: str
|
|
51
94
|
agent: str
|
|
52
95
|
project_id: str
|
|
53
96
|
condition: str # "form with multiple required fields"
|
|
54
|
-
strategy: str
|
|
97
|
+
strategy: str # "test happy path first, then individual validation"
|
|
55
98
|
confidence: float # 0.0 to 1.0
|
|
56
99
|
occurrence_count: int
|
|
57
100
|
success_count: int
|
|
@@ -75,6 +118,7 @@ class Outcome:
|
|
|
75
118
|
|
|
76
119
|
Outcomes are raw data that can be consolidated into heuristics.
|
|
77
120
|
"""
|
|
121
|
+
|
|
78
122
|
id: str
|
|
79
123
|
agent: str
|
|
80
124
|
project_id: str
|
|
@@ -85,7 +129,7 @@ class Outcome:
|
|
|
85
129
|
duration_ms: Optional[int] = None
|
|
86
130
|
error_message: Optional[str] = None
|
|
87
131
|
user_feedback: Optional[str] = None
|
|
88
|
-
timestamp: datetime = field(default_factory=datetime.
|
|
132
|
+
timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
89
133
|
embedding: Optional[List[float]] = None
|
|
90
134
|
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
91
135
|
|
|
@@ -97,13 +141,14 @@ class UserPreference:
|
|
|
97
141
|
|
|
98
142
|
Persists across sessions so users don't repeat themselves.
|
|
99
143
|
"""
|
|
144
|
+
|
|
100
145
|
id: str
|
|
101
146
|
user_id: str
|
|
102
147
|
category: str # "communication", "code_style", "workflow"
|
|
103
148
|
preference: str # "No emojis in documentation"
|
|
104
149
|
source: str # "explicit_instruction", "inferred_from_correction"
|
|
105
150
|
confidence: float = 1.0 # Lower for inferred preferences
|
|
106
|
-
timestamp: datetime = field(default_factory=datetime.
|
|
151
|
+
timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
107
152
|
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
108
153
|
|
|
109
154
|
|
|
@@ -114,6 +159,7 @@ class DomainKnowledge:
|
|
|
114
159
|
|
|
115
160
|
Different from heuristics - these are facts, not strategies.
|
|
116
161
|
"""
|
|
162
|
+
|
|
117
163
|
id: str
|
|
118
164
|
agent: str
|
|
119
165
|
project_id: str
|
|
@@ -121,7 +167,7 @@ class DomainKnowledge:
|
|
|
121
167
|
fact: str # "Login endpoint uses JWT with 24h expiry"
|
|
122
168
|
source: str # "code_analysis", "documentation", "user_stated"
|
|
123
169
|
confidence: float = 1.0
|
|
124
|
-
last_verified: datetime = field(default_factory=datetime.
|
|
170
|
+
last_verified: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
125
171
|
embedding: Optional[List[float]] = None
|
|
126
172
|
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
127
173
|
|
|
@@ -133,6 +179,7 @@ class AntiPattern:
|
|
|
133
179
|
|
|
134
180
|
Helps agents avoid repeating mistakes.
|
|
135
181
|
"""
|
|
182
|
+
|
|
136
183
|
id: str
|
|
137
184
|
agent: str
|
|
138
185
|
project_id: str
|
|
@@ -141,7 +188,7 @@ class AntiPattern:
|
|
|
141
188
|
better_alternative: str # "Use explicit waits with conditions"
|
|
142
189
|
occurrence_count: int
|
|
143
190
|
last_seen: datetime
|
|
144
|
-
created_at: datetime = field(default_factory=datetime.
|
|
191
|
+
created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
145
192
|
embedding: Optional[List[float]] = None
|
|
146
193
|
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
147
194
|
|
|
@@ -153,6 +200,7 @@ class MemorySlice:
|
|
|
153
200
|
|
|
154
201
|
This is what gets injected per-call - must stay under token budget.
|
|
155
202
|
"""
|
|
203
|
+
|
|
156
204
|
heuristics: List[Heuristic] = field(default_factory=list)
|
|
157
205
|
outcomes: List[Outcome] = field(default_factory=list)
|
|
158
206
|
preferences: List[UserPreference] = field(default_factory=list)
|
|
@@ -200,7 +248,7 @@ class MemorySlice:
|
|
|
200
248
|
|
|
201
249
|
# Basic token estimation (rough: 1 token ~ 4 chars)
|
|
202
250
|
if len(result) > max_tokens * 4:
|
|
203
|
-
result = result[:max_tokens * 4] + "\n[truncated]"
|
|
251
|
+
result = result[: max_tokens * 4] + "\n[truncated]"
|
|
204
252
|
|
|
205
253
|
return result
|
|
206
254
|
|
|
@@ -208,9 +256,9 @@ class MemorySlice:
|
|
|
208
256
|
def total_items(self) -> int:
|
|
209
257
|
"""Total number of memory items in this slice."""
|
|
210
258
|
return (
|
|
211
|
-
len(self.heuristics)
|
|
212
|
-
len(self.outcomes)
|
|
213
|
-
len(self.preferences)
|
|
214
|
-
len(self.domain_knowledge)
|
|
215
|
-
len(self.anti_patterns)
|
|
259
|
+
len(self.heuristics)
|
|
260
|
+
+ len(self.outcomes)
|
|
261
|
+
+ len(self.preferences)
|
|
262
|
+
+ len(self.domain_knowledge)
|
|
263
|
+
+ len(self.anti_patterns)
|
|
216
264
|
)
|