neural-memory 0.1.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 (55) hide show
  1. neural_memory/__init__.py +38 -0
  2. neural_memory/cli/__init__.py +15 -0
  3. neural_memory/cli/__main__.py +6 -0
  4. neural_memory/cli/config.py +176 -0
  5. neural_memory/cli/main.py +2702 -0
  6. neural_memory/cli/storage.py +169 -0
  7. neural_memory/cli/tui.py +471 -0
  8. neural_memory/core/__init__.py +52 -0
  9. neural_memory/core/brain.py +301 -0
  10. neural_memory/core/brain_mode.py +273 -0
  11. neural_memory/core/fiber.py +236 -0
  12. neural_memory/core/memory_types.py +331 -0
  13. neural_memory/core/neuron.py +168 -0
  14. neural_memory/core/project.py +257 -0
  15. neural_memory/core/synapse.py +215 -0
  16. neural_memory/engine/__init__.py +15 -0
  17. neural_memory/engine/activation.py +335 -0
  18. neural_memory/engine/encoder.py +391 -0
  19. neural_memory/engine/retrieval.py +440 -0
  20. neural_memory/extraction/__init__.py +42 -0
  21. neural_memory/extraction/entities.py +547 -0
  22. neural_memory/extraction/parser.py +337 -0
  23. neural_memory/extraction/router.py +396 -0
  24. neural_memory/extraction/temporal.py +428 -0
  25. neural_memory/mcp/__init__.py +9 -0
  26. neural_memory/mcp/__main__.py +6 -0
  27. neural_memory/mcp/server.py +621 -0
  28. neural_memory/py.typed +0 -0
  29. neural_memory/safety/__init__.py +31 -0
  30. neural_memory/safety/freshness.py +238 -0
  31. neural_memory/safety/sensitive.py +304 -0
  32. neural_memory/server/__init__.py +5 -0
  33. neural_memory/server/app.py +99 -0
  34. neural_memory/server/dependencies.py +33 -0
  35. neural_memory/server/models.py +138 -0
  36. neural_memory/server/routes/__init__.py +7 -0
  37. neural_memory/server/routes/brain.py +221 -0
  38. neural_memory/server/routes/memory.py +169 -0
  39. neural_memory/server/routes/sync.py +387 -0
  40. neural_memory/storage/__init__.py +17 -0
  41. neural_memory/storage/base.py +441 -0
  42. neural_memory/storage/factory.py +329 -0
  43. neural_memory/storage/memory_store.py +896 -0
  44. neural_memory/storage/shared_store.py +650 -0
  45. neural_memory/storage/sqlite_store.py +1613 -0
  46. neural_memory/sync/__init__.py +5 -0
  47. neural_memory/sync/client.py +435 -0
  48. neural_memory/unified_config.py +315 -0
  49. neural_memory/utils/__init__.py +5 -0
  50. neural_memory/utils/config.py +98 -0
  51. neural_memory-0.1.0.dist-info/METADATA +314 -0
  52. neural_memory-0.1.0.dist-info/RECORD +55 -0
  53. neural_memory-0.1.0.dist-info/WHEEL +4 -0
  54. neural_memory-0.1.0.dist-info/entry_points.txt +4 -0
  55. neural_memory-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,236 @@
1
+ """Fiber data structures - memory clusters of related neurons."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from datetime import datetime
7
+ from typing import Any
8
+ from uuid import uuid4
9
+
10
+
11
+ @dataclass
12
+ class Fiber:
13
+ """
14
+ A fiber represents a memory cluster - a subgraph of related neurons.
15
+
16
+ Fibers bundle together neurons and synapses that form a coherent
17
+ memory or concept. They act as retrieval units and can be
18
+ compressed into summaries over time.
19
+
20
+ Attributes:
21
+ id: Unique identifier
22
+ neuron_ids: Set of neuron IDs in this fiber
23
+ synapse_ids: Set of synapse IDs connecting neurons in this fiber
24
+ anchor_neuron_id: Primary entry point neuron for this fiber
25
+ time_start: Earliest timestamp in this memory
26
+ time_end: Latest timestamp in this memory
27
+ coherence: How tightly connected the neurons are (0.0 - 1.0)
28
+ salience: Importance/relevance score (0.0 - 1.0)
29
+ frequency: Number of times this fiber has been accessed
30
+ summary: Optional compressed text summary
31
+ tags: Optional tags for categorization
32
+ metadata: Additional fiber-specific data
33
+ created_at: When this fiber was created
34
+ """
35
+
36
+ id: str
37
+ neuron_ids: set[str]
38
+ synapse_ids: set[str]
39
+ anchor_neuron_id: str
40
+ time_start: datetime | None = None
41
+ time_end: datetime | None = None
42
+ coherence: float = 0.0
43
+ salience: float = 0.0
44
+ frequency: int = 0
45
+ summary: str | None = None
46
+ tags: set[str] = field(default_factory=set)
47
+ metadata: dict[str, Any] = field(default_factory=dict)
48
+ created_at: datetime = field(default_factory=datetime.utcnow)
49
+
50
+ @classmethod
51
+ def create(
52
+ cls,
53
+ neuron_ids: set[str],
54
+ synapse_ids: set[str],
55
+ anchor_neuron_id: str,
56
+ time_start: datetime | None = None,
57
+ time_end: datetime | None = None,
58
+ summary: str | None = None,
59
+ tags: set[str] | None = None,
60
+ metadata: dict[str, Any] | None = None,
61
+ fiber_id: str | None = None,
62
+ ) -> Fiber:
63
+ """
64
+ Factory method to create a new Fiber.
65
+
66
+ Args:
67
+ neuron_ids: Set of neuron IDs
68
+ synapse_ids: Set of synapse IDs
69
+ anchor_neuron_id: Primary entry point
70
+ time_start: Optional start time
71
+ time_end: Optional end time
72
+ summary: Optional text summary
73
+ tags: Optional tags
74
+ metadata: Optional metadata
75
+ fiber_id: Optional explicit ID
76
+
77
+ Returns:
78
+ A new Fiber instance
79
+ """
80
+ if anchor_neuron_id not in neuron_ids:
81
+ raise ValueError(f"Anchor neuron {anchor_neuron_id} must be in neuron_ids")
82
+
83
+ return cls(
84
+ id=fiber_id or str(uuid4()),
85
+ neuron_ids=neuron_ids,
86
+ synapse_ids=synapse_ids,
87
+ anchor_neuron_id=anchor_neuron_id,
88
+ time_start=time_start,
89
+ time_end=time_end,
90
+ summary=summary,
91
+ tags=tags or set(),
92
+ metadata=metadata or {},
93
+ created_at=datetime.utcnow(),
94
+ )
95
+
96
+ def access(self) -> Fiber:
97
+ """
98
+ Create a new Fiber with incremented access frequency.
99
+
100
+ Returns:
101
+ New Fiber with frequency + 1
102
+ """
103
+ return Fiber(
104
+ id=self.id,
105
+ neuron_ids=self.neuron_ids,
106
+ synapse_ids=self.synapse_ids,
107
+ anchor_neuron_id=self.anchor_neuron_id,
108
+ time_start=self.time_start,
109
+ time_end=self.time_end,
110
+ coherence=self.coherence,
111
+ salience=self.salience,
112
+ frequency=self.frequency + 1,
113
+ summary=self.summary,
114
+ tags=self.tags,
115
+ metadata=self.metadata,
116
+ created_at=self.created_at,
117
+ )
118
+
119
+ def with_salience(self, salience: float) -> Fiber:
120
+ """
121
+ Create a new Fiber with updated salience.
122
+
123
+ Args:
124
+ salience: New salience value (clamped to 0.0-1.0)
125
+
126
+ Returns:
127
+ New Fiber with updated salience
128
+ """
129
+ return Fiber(
130
+ id=self.id,
131
+ neuron_ids=self.neuron_ids,
132
+ synapse_ids=self.synapse_ids,
133
+ anchor_neuron_id=self.anchor_neuron_id,
134
+ time_start=self.time_start,
135
+ time_end=self.time_end,
136
+ coherence=self.coherence,
137
+ salience=max(0.0, min(1.0, salience)),
138
+ frequency=self.frequency,
139
+ summary=self.summary,
140
+ tags=self.tags,
141
+ metadata=self.metadata,
142
+ created_at=self.created_at,
143
+ )
144
+
145
+ def with_summary(self, summary: str) -> Fiber:
146
+ """
147
+ Create a new Fiber with a summary.
148
+
149
+ Args:
150
+ summary: The summary text
151
+
152
+ Returns:
153
+ New Fiber with summary
154
+ """
155
+ return Fiber(
156
+ id=self.id,
157
+ neuron_ids=self.neuron_ids,
158
+ synapse_ids=self.synapse_ids,
159
+ anchor_neuron_id=self.anchor_neuron_id,
160
+ time_start=self.time_start,
161
+ time_end=self.time_end,
162
+ coherence=self.coherence,
163
+ salience=self.salience,
164
+ frequency=self.frequency,
165
+ summary=summary,
166
+ tags=self.tags,
167
+ metadata=self.metadata,
168
+ created_at=self.created_at,
169
+ )
170
+
171
+ def add_tags(self, *new_tags: str) -> Fiber:
172
+ """
173
+ Create a new Fiber with additional tags.
174
+
175
+ Args:
176
+ *new_tags: Tags to add
177
+
178
+ Returns:
179
+ New Fiber with merged tags
180
+ """
181
+ return Fiber(
182
+ id=self.id,
183
+ neuron_ids=self.neuron_ids,
184
+ synapse_ids=self.synapse_ids,
185
+ anchor_neuron_id=self.anchor_neuron_id,
186
+ time_start=self.time_start,
187
+ time_end=self.time_end,
188
+ coherence=self.coherence,
189
+ salience=self.salience,
190
+ frequency=self.frequency,
191
+ summary=self.summary,
192
+ tags=self.tags | set(new_tags),
193
+ metadata=self.metadata,
194
+ created_at=self.created_at,
195
+ )
196
+
197
+ @property
198
+ def neuron_count(self) -> int:
199
+ """Number of neurons in this fiber."""
200
+ return len(self.neuron_ids)
201
+
202
+ @property
203
+ def synapse_count(self) -> int:
204
+ """Number of synapses in this fiber."""
205
+ return len(self.synapse_ids)
206
+
207
+ @property
208
+ def time_span(self) -> float | None:
209
+ """
210
+ Duration of this memory in seconds.
211
+
212
+ Returns None if time bounds are not set.
213
+ """
214
+ if self.time_start and self.time_end:
215
+ return (self.time_end - self.time_start).total_seconds()
216
+ return None
217
+
218
+ def contains_neuron(self, neuron_id: str) -> bool:
219
+ """Check if this fiber contains a specific neuron."""
220
+ return neuron_id in self.neuron_ids
221
+
222
+ def overlaps_time(self, start: datetime, end: datetime) -> bool:
223
+ """
224
+ Check if this fiber's time range overlaps with given range.
225
+
226
+ Args:
227
+ start: Query start time
228
+ end: Query end time
229
+
230
+ Returns:
231
+ True if there is any overlap
232
+ """
233
+ if self.time_start is None or self.time_end is None:
234
+ return False
235
+
236
+ return self.time_start <= end and self.time_end >= start
@@ -0,0 +1,331 @@
1
+ """Memory types and classification for Neural Memory.
2
+
3
+ Integrates MemoCore concepts: typed memories with priority, expiry, and provenance.
4
+ This enables smarter query routing and memory lifecycle management.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from dataclasses import dataclass, field
10
+ from datetime import datetime, timedelta
11
+ from enum import IntEnum, StrEnum
12
+ from typing import Any
13
+
14
+
15
+ class MemoryType(StrEnum):
16
+ """Types of memories based on their nature and purpose."""
17
+
18
+ # Core types from MemoCore
19
+ FACT = "fact" # Objective information: "Python 3.11 was released in Oct 2022"
20
+ DECISION = "decision" # Choices made: "We decided to use PostgreSQL"
21
+ PREFERENCE = "preference" # User preferences: "I prefer tabs over spaces"
22
+ TODO = "todo" # Action items: "Need to refactor auth module"
23
+ INSIGHT = "insight" # Learned patterns: "This codebase uses dependency injection"
24
+ CONTEXT = "context" # Situational info: "Working on project X for client Y"
25
+ INSTRUCTION = "instruction" # User guidelines: "Always use type hints"
26
+
27
+ # Additional useful types
28
+ ERROR = "error" # Error patterns: "This API returns 429 on rate limit"
29
+ WORKFLOW = "workflow" # Process patterns: "Deploy flow: test -> stage -> prod"
30
+ REFERENCE = "reference" # External refs: "Docs at https://..."
31
+
32
+
33
+ class Priority(IntEnum):
34
+ """Memory priority levels (0-10 scale)."""
35
+
36
+ LOWEST = 0
37
+ LOW = 2
38
+ NORMAL = 5
39
+ HIGH = 7
40
+ CRITICAL = 10
41
+
42
+ @classmethod
43
+ def from_int(cls, value: int) -> Priority:
44
+ """Convert integer to nearest Priority level."""
45
+ if value <= 1:
46
+ return cls.LOWEST
47
+ elif value <= 3:
48
+ return cls.LOW
49
+ elif value <= 6:
50
+ return cls.NORMAL
51
+ elif value <= 8:
52
+ return cls.HIGH
53
+ else:
54
+ return cls.CRITICAL
55
+
56
+
57
+ class Confidence(StrEnum):
58
+ """Confidence level in the memory's accuracy."""
59
+
60
+ VERIFIED = "verified" # Confirmed by user or external source
61
+ HIGH = "high" # Very likely accurate
62
+ MEDIUM = "medium" # Probably accurate
63
+ LOW = "low" # Uncertain, needs verification
64
+ INFERRED = "inferred" # AI-inferred, may be wrong
65
+
66
+
67
+ @dataclass(frozen=True)
68
+ class Provenance:
69
+ """Tracks the origin and reliability of a memory.
70
+
71
+ Attributes:
72
+ source: Where this memory came from
73
+ confidence: How reliable this memory is
74
+ verified: Whether explicitly verified by user
75
+ verified_at: When verification happened
76
+ created_by: Who/what created this memory
77
+ last_confirmed: When last confirmed as still valid
78
+ """
79
+
80
+ source: str # "user_input", "ai_inference", "import", "observation"
81
+ confidence: Confidence = Confidence.MEDIUM
82
+ verified: bool = False
83
+ verified_at: datetime | None = None
84
+ created_by: str = "user"
85
+ last_confirmed: datetime | None = None
86
+
87
+ def verify(self) -> Provenance:
88
+ """Create a new Provenance marked as verified."""
89
+ return Provenance(
90
+ source=self.source,
91
+ confidence=Confidence.VERIFIED,
92
+ verified=True,
93
+ verified_at=datetime.utcnow(),
94
+ created_by=self.created_by,
95
+ last_confirmed=datetime.utcnow(),
96
+ )
97
+
98
+ def confirm(self) -> Provenance:
99
+ """Create a new Provenance with updated confirmation time."""
100
+ return Provenance(
101
+ source=self.source,
102
+ confidence=self.confidence,
103
+ verified=self.verified,
104
+ verified_at=self.verified_at,
105
+ created_by=self.created_by,
106
+ last_confirmed=datetime.utcnow(),
107
+ )
108
+
109
+
110
+ @dataclass(frozen=True)
111
+ class TypedMemory:
112
+ """A memory with type classification, priority, and lifecycle metadata.
113
+
114
+ This wraps around fibers to add MemoCore-style memory management.
115
+
116
+ Attributes:
117
+ fiber_id: Reference to the underlying Fiber
118
+ memory_type: Classification of this memory
119
+ priority: Importance level (0-10)
120
+ provenance: Origin and reliability info
121
+ expires_at: Optional expiration timestamp
122
+ project_id: Optional project scope
123
+ tags: Additional categorization tags
124
+ metadata: Extra type-specific data
125
+ created_at: Creation timestamp
126
+ """
127
+
128
+ fiber_id: str
129
+ memory_type: MemoryType
130
+ priority: Priority = Priority.NORMAL
131
+ provenance: Provenance = field(default_factory=lambda: Provenance(source="user_input"))
132
+ expires_at: datetime | None = None
133
+ project_id: str | None = None
134
+ tags: frozenset[str] = field(default_factory=frozenset)
135
+ metadata: dict[str, Any] = field(default_factory=dict)
136
+ created_at: datetime = field(default_factory=datetime.utcnow)
137
+
138
+ @classmethod
139
+ def create(
140
+ cls,
141
+ fiber_id: str,
142
+ memory_type: MemoryType,
143
+ priority: Priority | int = Priority.NORMAL,
144
+ source: str = "user_input",
145
+ confidence: Confidence = Confidence.MEDIUM,
146
+ expires_in_days: int | None = None,
147
+ project_id: str | None = None,
148
+ tags: set[str] | None = None,
149
+ metadata: dict[str, Any] | None = None,
150
+ ) -> TypedMemory:
151
+ """Factory method to create a TypedMemory.
152
+
153
+ Args:
154
+ fiber_id: The underlying fiber ID
155
+ memory_type: Type of memory
156
+ priority: Priority level (int or Priority enum)
157
+ source: Source of this memory
158
+ confidence: Confidence level
159
+ expires_in_days: Optional days until expiry
160
+ project_id: Optional project scope
161
+ tags: Optional tags
162
+ metadata: Optional metadata
163
+
164
+ Returns:
165
+ A new TypedMemory instance
166
+ """
167
+ if isinstance(priority, int):
168
+ priority = Priority.from_int(priority)
169
+
170
+ expires_at = None
171
+ if expires_in_days is not None:
172
+ expires_at = datetime.utcnow() + timedelta(days=expires_in_days)
173
+
174
+ return cls(
175
+ fiber_id=fiber_id,
176
+ memory_type=memory_type,
177
+ priority=priority,
178
+ provenance=Provenance(source=source, confidence=confidence),
179
+ expires_at=expires_at,
180
+ project_id=project_id,
181
+ tags=frozenset(tags) if tags else frozenset(),
182
+ metadata=metadata or {},
183
+ created_at=datetime.utcnow(),
184
+ )
185
+
186
+ @property
187
+ def is_expired(self) -> bool:
188
+ """Check if this memory has expired."""
189
+ if self.expires_at is None:
190
+ return False
191
+ return datetime.utcnow() > self.expires_at
192
+
193
+ @property
194
+ def days_until_expiry(self) -> int | None:
195
+ """Days until this memory expires, or None if no expiry."""
196
+ if self.expires_at is None:
197
+ return None
198
+ delta = self.expires_at - datetime.utcnow()
199
+ return max(0, delta.days)
200
+
201
+ def with_priority(self, priority: Priority | int) -> TypedMemory:
202
+ """Create a new TypedMemory with updated priority."""
203
+ if isinstance(priority, int):
204
+ priority = Priority.from_int(priority)
205
+ return TypedMemory(
206
+ fiber_id=self.fiber_id,
207
+ memory_type=self.memory_type,
208
+ priority=priority,
209
+ provenance=self.provenance,
210
+ expires_at=self.expires_at,
211
+ project_id=self.project_id,
212
+ tags=self.tags,
213
+ metadata=self.metadata,
214
+ created_at=self.created_at,
215
+ )
216
+
217
+ def verify(self) -> TypedMemory:
218
+ """Create a new TypedMemory marked as verified."""
219
+ return TypedMemory(
220
+ fiber_id=self.fiber_id,
221
+ memory_type=self.memory_type,
222
+ priority=self.priority,
223
+ provenance=self.provenance.verify(),
224
+ expires_at=self.expires_at,
225
+ project_id=self.project_id,
226
+ tags=self.tags,
227
+ metadata=self.metadata,
228
+ created_at=self.created_at,
229
+ )
230
+
231
+ def extend_expiry(self, days: int) -> TypedMemory:
232
+ """Create a new TypedMemory with extended expiry."""
233
+ new_expiry = datetime.utcnow() + timedelta(days=days)
234
+ return TypedMemory(
235
+ fiber_id=self.fiber_id,
236
+ memory_type=self.memory_type,
237
+ priority=self.priority,
238
+ provenance=self.provenance,
239
+ expires_at=new_expiry,
240
+ project_id=self.project_id,
241
+ tags=self.tags,
242
+ metadata=self.metadata,
243
+ created_at=self.created_at,
244
+ )
245
+
246
+
247
+ # Default expiry settings per memory type
248
+ DEFAULT_EXPIRY_DAYS: dict[MemoryType, int | None] = {
249
+ MemoryType.FACT: None, # Facts don't expire by default
250
+ MemoryType.DECISION: 90, # Decisions may become stale
251
+ MemoryType.PREFERENCE: None, # Preferences persist
252
+ MemoryType.TODO: 30, # TODOs should be acted on
253
+ MemoryType.INSIGHT: 180, # Insights may become outdated
254
+ MemoryType.CONTEXT: 7, # Context is usually short-term
255
+ MemoryType.INSTRUCTION: None, # Instructions persist
256
+ MemoryType.ERROR: 30, # Error patterns may get fixed
257
+ MemoryType.WORKFLOW: 365, # Workflows change slowly
258
+ MemoryType.REFERENCE: None, # References persist
259
+ }
260
+
261
+
262
+ def suggest_memory_type(content: str) -> MemoryType:
263
+ """Suggest a memory type based on content analysis.
264
+
265
+ This is a simple heuristic. For production, use NLP.
266
+
267
+ Args:
268
+ content: The memory content to analyze
269
+
270
+ Returns:
271
+ Suggested MemoryType
272
+ """
273
+ content_lower = content.lower()
274
+
275
+ # TODO patterns (highest priority - actionable)
276
+ if any(
277
+ kw in content_lower
278
+ for kw in ["todo", "need to", "should", "must", "fix", "implement", "add"]
279
+ ):
280
+ return MemoryType.TODO
281
+
282
+ # Decision patterns
283
+ if any(
284
+ kw in content_lower
285
+ for kw in ["decided", "chose", "will use", "going with", "picked", "selected"]
286
+ ):
287
+ return MemoryType.DECISION
288
+
289
+ # Instruction patterns (check BEFORE preference - "always use" vs "always")
290
+ if any(
291
+ kw in content_lower
292
+ for kw in [
293
+ "always use",
294
+ "never use",
295
+ "make sure",
296
+ "remember to",
297
+ "don't forget",
298
+ ]
299
+ ):
300
+ return MemoryType.INSTRUCTION
301
+
302
+ # Preference patterns
303
+ if any(kw in content_lower for kw in ["prefer", "like", "favorite", "hate"]):
304
+ return MemoryType.PREFERENCE
305
+
306
+ # Insight patterns (check BEFORE error - "discovered" vs "issue")
307
+ if any(
308
+ kw in content_lower
309
+ for kw in ["learned", "realized", "discovered", "found that", "turns out"]
310
+ ):
311
+ return MemoryType.INSIGHT
312
+
313
+ # Error patterns
314
+ if any(
315
+ kw in content_lower
316
+ for kw in ["error", "bug", "issue", "problem", "fail", "crash", "exception"]
317
+ ):
318
+ return MemoryType.ERROR
319
+
320
+ # Workflow patterns
321
+ if any(
322
+ kw in content_lower for kw in ["workflow", "process", "step", "flow", "pipeline", "deploy"]
323
+ ):
324
+ return MemoryType.WORKFLOW
325
+
326
+ # Reference patterns
327
+ if any(kw in content_lower for kw in ["http", "https", "docs", "documentation"]):
328
+ return MemoryType.REFERENCE
329
+
330
+ # Default to fact
331
+ return MemoryType.FACT