-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathmemory.py
More file actions
56 lines (37 loc) · 1.52 KB
/
memory.py
File metadata and controls
56 lines (37 loc) · 1.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
"""Memory ports — Hermes memory split into 3 independent axes (★②).
Store (where), Recall (what to fetch), Extractor (how new facts are made) each
evolve on their own. V1 = in-memory dict + inject-all + manual ``/remember``;
v1.5 swaps Store→SQLite or Recall→keyword as a single adapter add.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Protocol, Sequence, runtime_checkable
from ..types import Message
@dataclass
class Fact:
"""A remembered statement, scoped to a user/conversation."""
id: str
owner: str # user_id or scope key
text: str
source: str = "manual" # "manual" (/remember) | "auto" (v1.5 extractor)
ts: float = 0.0
@runtime_checkable
class StorePort(Protocol):
"""Where facts live. Axis 1."""
async def add(self, fact: Fact) -> None: ...
async def all(self, owner: str) -> list[Fact]: ...
@runtime_checkable
class RecallPort(Protocol):
"""Which facts to surface for the current question. Axis 2.
V1 returns everything; v1.5 filters by keyword, v2 by vector similarity.
"""
async def recall(self, owner: str, query: str, store: StorePort) -> list[Fact]:
...
@runtime_checkable
class ExtractorPort(Protocol):
"""How new facts get created. Axis 3.
V1 only the explicit ``/remember`` path produces facts (so ``extract``
yields nothing); v1.5 mines the transcript with an LLM.
"""
async def extract(self, owner: str, transcript: Sequence[Message]) -> list[Fact]:
...