pi-hermes-memory 0.1.0 → 0.2.1
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.
- package/README.md +209 -78
- package/docs/0.2/PLAN.md +290 -0
- package/docs/0.2/TASKS.md +134 -0
- package/docs/0.2/TEST-PLAN.md +216 -0
- package/docs/ROADMAP.md +245 -135
- package/package.json +9 -5
- package/src/config.ts +11 -0
- package/src/constants.ts +78 -3
- package/src/handlers/auto-consolidate.ts +94 -0
- package/src/handlers/background-review.ts +42 -3
- package/src/handlers/correction-detector.ts +156 -0
- package/src/handlers/insights.ts +20 -1
- package/src/handlers/session-flush.ts +1 -0
- package/src/handlers/skill-auto-trigger.ts +108 -0
- package/src/handlers/skills-command.ts +38 -0
- package/src/index.ts +66 -13
- package/src/store/memory-store.ts +75 -21
- package/src/store/skill-store.ts +292 -0
- package/src/tools/memory-tool.ts +25 -6
- package/src/tools/skill-tool.ts +142 -0
- package/src/types.ts +42 -0
package/docs/ROADMAP.md
CHANGED
|
@@ -14,122 +14,204 @@
|
|
|
14
14
|
- 119 automated tests, 0 type errors
|
|
15
15
|
- Atomic writes (temp + rename)
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
---
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
graph TB
|
|
21
|
-
subgraph "v0.1.0 — Current"
|
|
22
|
-
T1["memory tool<br/>(add / replace / remove)"]
|
|
23
|
-
SC["Content Scanner<br/>(injection · exfiltration · unicode)"]
|
|
24
|
-
MD["Markdown Backend<br/>MEMORY.md · USER.md"]
|
|
25
|
-
FS["Frozen Snapshot<br/>(system prompt injection)"]
|
|
26
|
-
BL["Background Review<br/>(pi.exec child process)"]
|
|
27
|
-
SF["Session Flush<br/>(compact · shutdown)"]
|
|
28
|
-
IC["/memory-insights<br/>(command)"]
|
|
29
|
-
CF["Config File<br/>(hermes-memory-config.json)"]
|
|
30
|
-
end
|
|
19
|
+
## Hermes Agent Competitive Analysis
|
|
31
20
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
21
|
+
> Research conducted 2026-04-26. Sources: [hermes-agent.ai](https://hermes-agent.ai/blog/hermes-agent-memory-system), [GitHub README](https://github.com/NousResearch/Hermes-Agent), [official docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory), [skills docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/skills).
|
|
22
|
+
|
|
23
|
+
### Hermes 3-Layer Memory Architecture
|
|
24
|
+
|
|
25
|
+
Hermes has three memory subsystems operating at different timescales:
|
|
26
|
+
|
|
27
|
+
| Layer | What | Capacity | Token Cost |
|
|
28
|
+
|---|---|---|---|
|
|
29
|
+
| **L1: Persistent Memory** (MEMORY.md + USER.md) | Curated facts, frozen snapshot injection | ~1,300 tokens total | Fixed per session |
|
|
30
|
+
| **L2: Episodic Memory** (Skills System) | Procedural memory — SKILL.md files created from experience, progressive disclosure | Unlimited | ~3K tokens for index, full content on demand |
|
|
31
|
+
| **L3: Session Search** (SQLite FTS5) | Full-text search over ALL conversations | Unlimited | On-demand only |
|
|
32
|
+
|
|
33
|
+
Plus **L4: External Providers** — Honcho, Mem0, Hindsight, etc. for deeper user modeling.
|
|
34
|
+
|
|
35
|
+
### Gap Analysis: Hermes vs. Our v0.1
|
|
36
|
+
|
|
37
|
+
| Capability | Hermes | Our v0.1 | Priority |
|
|
38
|
+
|---|---|---|---|
|
|
39
|
+
| L1: Persistent Memory (MEMORY.md + USER.md) | ✅ | ✅ **Covered** | — |
|
|
40
|
+
| Frozen snapshot + prefix cache preservation | ✅ | ✅ **Covered** | — |
|
|
41
|
+
| Content scanning (injection, exfil, unicode) | ✅ | ✅ **Covered** | — |
|
|
42
|
+
| Background learning loop (periodic nudge) | ✅ | ✅ **Covered** | — |
|
|
43
|
+
| Session flush (compact + shutdown) | ✅ | ✅ **Covered** | — |
|
|
44
|
+
| **L2: Skills / Procedural Memory** | ✅ Auto-created after complex tasks, progressive disclosure, SKILL.md format | ❌ **MISSING** — our COMBINED_REVIEW_PROMPT already asks about skills but there's no skill tool | 🔴 **Critical** |
|
|
45
|
+
| **L3: Session Search** | ✅ SQLite FTS5 over all conversations, on-demand retrieval + summarization | ❌ **MISSING** — no cross-session recall at all | 🔴 **Critical** |
|
|
46
|
+
| **Auto-consolidation when memory full** | ✅ Agent merges/removes entries automatically | ❌ Returns error "Replace or remove existing entries" | 🟡 **High** |
|
|
47
|
+
| **Correction-triggered memory save** | ✅ Detects user corrections for immediate save | ❌ Only saves on nudge interval (every 10 turns) | 🟡 **High** |
|
|
48
|
+
| **Tool-call-aware nudge** | ✅ Self-evaluation every 15 tool calls | ❌ Only turn-count based | 🟡 **Medium** |
|
|
49
|
+
| **Progressive disclosure** | ✅ 3-level loading (index → full → references) | ❌ Not applicable (no skills yet) | 🟡 **Depends on Skills** |
|
|
50
|
+
| **Memory aging / staleness tracking** | ✅ Consolidation removes superseded entries | ❌ Entries live forever until manually removed | 🟠 **Medium** |
|
|
51
|
+
| **Context fencing** (memory-context XML tags) | ✅ Prevents prompt injection through stored memories | ❌ Raw injection | 🟠 **Medium** |
|
|
52
|
+
| **External providers** (Honcho, Mem0, etc.) | ✅ 8+ external provider plugins | ⏳ Planned for v0.4 | 🟢 **Deferred** |
|
|
53
|
+
| **Skills Hub / Community skills** | ✅ agentskills.io, search, install, audit | ❌ Not applicable (Pi has its own skill system) | ⚪ **N/A** |
|
|
54
|
+
| **Cross-platform messaging** | ✅ Telegram, Discord, Slack, WhatsApp, Signal | ❌ Not applicable (Pi extension, not standalone agent) | ⚪ **N/A** |
|
|
55
|
+
|
|
56
|
+
### Key Painpoints Hermes Solves That We Must Address
|
|
57
|
+
|
|
58
|
+
1. **"Goldfish memory"** — Every session starts from zero, user re-explains preferences, stack, conventions. Our L1 solves this. ✅
|
|
59
|
+
|
|
60
|
+
2. **No procedural knowledge** — The agent forgets *how* it solved problems. After 60+ sessions, Hermes shows "anticipatory behavior" because it has skill documents from past experience. Our review prompt asks about skills but has nowhere to save them. 🔴
|
|
61
|
+
|
|
62
|
+
3. **No cross-session recall** — "Did we discuss X last week?" is unanswerable. Hermes searches all past conversations via FTS5. We have zero session search. 🔴
|
|
63
|
+
|
|
64
|
+
4. **Memory full = dead end** — When our memory hits capacity, we return an error and force the user/agent to manually fix it. Hermes auto-consolidates. 🟡
|
|
65
|
+
|
|
66
|
+
5. **Missed corrections** — User says "no, don't do that" and the agent only saves it 8 turns later at the next nudge. Hermes detects corrections immediately. 🟡
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Revised Roadmap
|
|
71
|
+
|
|
72
|
+
The roadmap is restructured based on the Hermes gap analysis. The biggest missing pieces are **Skills/Procedural Memory** and **Smart Curation** (auto-consolidation, correction detection). Session Search and External Providers stay in later phases.
|
|
46
73
|
|
|
47
74
|
```mermaid
|
|
48
|
-
graph
|
|
49
|
-
subgraph "v0.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
PI2["Context-Aware Injection<br/>(relevance-filtered)"]
|
|
55
|
-
PS["Project-Scoped Memory<br/>(keyed by cwd)"]
|
|
75
|
+
graph LR
|
|
76
|
+
subgraph "v0.1 ✅"
|
|
77
|
+
A[L1: Persistent Memory]
|
|
78
|
+
B[Content Scanner]
|
|
79
|
+
C[Background Review]
|
|
80
|
+
D[Session Flush]
|
|
56
81
|
end
|
|
57
82
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
style SC2 fill:#ff6600,stroke:#fff,color:#fff
|
|
65
|
-
style SA fill:#1282a2,stroke:#fff,color:#fff
|
|
66
|
-
style SQL fill:#0f3460,stroke:#fff,color:#fff
|
|
67
|
-
style PI2 fill:#16213e,stroke:#fff,color:#fff
|
|
68
|
-
style PS fill:#16213e,stroke:#fff,color:#fff
|
|
69
|
-
```
|
|
83
|
+
subgraph "v0.2 — Next"
|
|
84
|
+
E[Skill Tool]
|
|
85
|
+
F[Auto-Consolidation]
|
|
86
|
+
G[Correction Detection]
|
|
87
|
+
H[Tool-Call-Aware Nudge]
|
|
88
|
+
end
|
|
70
89
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
SC3["Content Scanner<br/>(unchanged — guards all backends)"]
|
|
76
|
-
SA3["Search Abstraction<br/>(MemoryBackend interface)"]
|
|
77
|
-
LOC["Local SQLite<br/>(default · offline)"]
|
|
78
|
-
M0["Mem0 Backend<br/>(vector search · cloud)"]
|
|
79
|
-
HON["Honcho Backend<br/>(dialectic reasoning · Hermes-native)"]
|
|
80
|
-
SEL["Selective Injection<br/>(search-relevant · project-scoped)"]
|
|
90
|
+
subgraph "v0.3"
|
|
91
|
+
I[Session Search]
|
|
92
|
+
J[Context Fencing]
|
|
93
|
+
K[Memory Aging]
|
|
81
94
|
end
|
|
82
95
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
M0 --> SEL
|
|
89
|
-
HON --> SEL
|
|
90
|
-
|
|
91
|
-
style T3 fill:#e94560,stroke:#fff,color:#fff
|
|
92
|
-
style SC3 fill:#ff6600,stroke:#fff,color:#fff
|
|
93
|
-
style SA3 fill:#1282a2,stroke:#fff,color:#fff
|
|
94
|
-
style LOC fill:#0f3460,stroke:#fff,color:#fff
|
|
95
|
-
style M0 fill:#6b21a8,stroke:#fff,color:#fff
|
|
96
|
-
style HON fill:#6b21a8,stroke:#fff,color:#fff
|
|
97
|
-
style SEL fill:#16213e,stroke:#fff,color:#fff
|
|
98
|
-
```
|
|
96
|
+
subgraph "v0.4"
|
|
97
|
+
L[MemoryBackend Interface]
|
|
98
|
+
M[SQLite Backend]
|
|
99
|
+
N[Project-Scoped Memory]
|
|
100
|
+
end
|
|
99
101
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
T4["memory tool<br/>(add / replace / remove / search / consolidate)"]
|
|
104
|
-
SC4["Content Scanner<br/>(extensible rule system)"]
|
|
105
|
-
SA4["Pluggable Backend<br/>(local · Mem0 · Honcho · custom)"]
|
|
106
|
-
CON["Smart Consolidation<br/>(structured extraction · dedup)"]
|
|
107
|
-
MUL["Multi-Agent Memory<br/>(shared context · scoping)"]
|
|
108
|
-
OBS["Observability<br/>(memory stats · usage · audit log)"]
|
|
102
|
+
subgraph "v0.5"
|
|
103
|
+
O[ExternalSync Interface]
|
|
104
|
+
P[Mem0 / Honcho]
|
|
109
105
|
end
|
|
110
106
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
107
|
+
A --> E
|
|
108
|
+
C --> F
|
|
109
|
+
C --> G
|
|
110
|
+
C --> H
|
|
111
|
+
E --> I
|
|
112
|
+
F --> K
|
|
113
|
+
A --> J
|
|
114
|
+
K --> L
|
|
115
|
+
I --> N
|
|
116
|
+
L --> O
|
|
117
|
+
O --> P
|
|
122
118
|
```
|
|
123
119
|
|
|
124
120
|
---
|
|
125
121
|
|
|
126
|
-
## v0.2.0 —
|
|
122
|
+
## v0.2.0 — Skills + Smart Curation
|
|
123
|
+
|
|
124
|
+
**Goal**: Close the two biggest gaps from the Hermes analysis — procedural memory (skills) and intelligent memory management (auto-consolidation, correction detection, tool-call-aware nudges).
|
|
125
|
+
|
|
126
|
+
**Why this before SQLite/Session Search**: Our `COMBINED_REVIEW_PROMPT` already asks the agent to save skills — but there's no skill tool. The review prompt is literally asking the agent to do something it can't do. Fixing this is the single highest-leverage change. Auto-consolidation and correction detection are small, high-impact additions to the existing curation system.
|
|
127
|
+
|
|
128
|
+
### Epic 1: Skill Tool + Procedural Memory
|
|
129
|
+
|
|
130
|
+
Hermes creates skills after complex tasks (5+ tool calls). Skills are SKILL.md files in `~/.hermes/skills/` with progressive disclosure. We adapt this for Pi's existing skill infrastructure at `~/.pi/agent/skills/`.
|
|
131
|
+
|
|
132
|
+
**Key insight**: Pi already has a skill system. Our skill tool should write SKILL.md files that are compatible with Pi's skill discovery. This means our skills are immediately usable as Pi slash commands — no separate ecosystem needed.
|
|
133
|
+
|
|
134
|
+
- [ ] `skill` tool — register via `pi.registerTool()` with actions: `create`, `patch`, `edit`, `delete`
|
|
135
|
+
- [ ] Skill storage in `~/.pi/agent/memory/skills/` (not `~/.pi/agent/skills/` — avoid conflicting with user's own skills)
|
|
136
|
+
- [ ] SKILL.md format — compatible with Pi's SKILL.md spec (frontmatter + markdown body)
|
|
137
|
+
- [ ] Progressive disclosure — skill index (name + description only) injected into system prompt, full content loaded on demand via `skill_view` action
|
|
138
|
+
- [ ] Auto-trigger after complex tasks — track tool calls per turn, trigger skill extraction at 5+ tool calls
|
|
139
|
+
- [ ] Background skill review — extend `COMBINED_REVIEW_PROMPT` to actually call the `skill` tool (currently it asks about skills but can't save them)
|
|
140
|
+
- [ ] Security — skill writes go through the same content scanner as memory writes
|
|
141
|
+
- [ ] `/memory-skills` command — list all agent-created skills with usage stats
|
|
142
|
+
|
|
143
|
+
**Reference**: Hermes `skill_manage` tool and `~/.hermes/skills/` directory structure. See [Hermes Skills docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/skills).
|
|
144
|
+
|
|
145
|
+
### Epic 2: Auto-Consolidation
|
|
146
|
+
|
|
147
|
+
When Hermes memory hits capacity, it automatically merges related entries and removes superseded ones. Our extension currently returns an error. This fixes the "memory full" dead end.
|
|
148
|
+
|
|
149
|
+
- [ ] When `add()` would exceed char limit, trigger auto-consolidation instead of returning error
|
|
150
|
+
- [ ] Consolidation via `pi.exec()` — spawn a one-shot process with a consolidation prompt
|
|
151
|
+
- [ ] Consolidation prompt — "Memory is at capacity. Merge related entries, remove outdated ones, keep the most important facts. Use the memory tool to make changes."
|
|
152
|
+
- [ ] After consolidation, retry the original `add()`
|
|
153
|
+
- [ ] Config: `autoConsolidate: boolean` (default: true)
|
|
154
|
+
- [ ] `/memory-consolidate` command — manual consolidation trigger
|
|
155
|
+
|
|
156
|
+
**Reference**: Hermes memory compression behavior described in [hermes-agent.ai memory blog](https://hermes-agent.ai/blog/hermes-agent-memory-system).
|
|
157
|
+
|
|
158
|
+
### Epic 3: Correction Detection + Immediate Save
|
|
159
|
+
|
|
160
|
+
Hermes detects user corrections and saves them immediately. Our extension only saves on the nudge interval (every 10 turns). User corrections are the most valuable memories — every missed correction is a repeated mistake.
|
|
161
|
+
|
|
162
|
+
- [ ] Correction detector — scan user messages for patterns: "no,", "wrong,", "actually,", "don't do that", "stop", "not like that", "I said..."
|
|
163
|
+
- [ ] On detection, trigger an immediate memory save prompt via `pi.exec()`
|
|
164
|
+
- [ ] Config: `correctionDetection: boolean` (default: true)
|
|
165
|
+
- [ ] Rate limit — max 1 correction save per 3 turns (avoid over-triggering on multi-turn corrections)
|
|
127
166
|
|
|
128
|
-
**
|
|
167
|
+
**Reference**: Hermes correction patterns inferred from the `MEMORY_TOOL_DESCRIPTION` priority list: "User preferences and corrections > environment facts > procedural knowledge."
|
|
129
168
|
|
|
130
|
-
###
|
|
169
|
+
### Epic 4: Tool-Call-Aware Nudge
|
|
131
170
|
|
|
132
|
-
|
|
171
|
+
Hermes runs a self-evaluation checkpoint every 15 tool calls. Our nudge is purely turn-count based. Complex tasks with many tool calls generate more valuable memories than simple conversations.
|
|
172
|
+
|
|
173
|
+
- [ ] Track tool call count per turn (via `tool_end` event or similar)
|
|
174
|
+
- [ ] Trigger background review when EITHER `nudgeInterval` turns OR `nudgeToolCalls` (default: 15) tool calls are reached
|
|
175
|
+
- [ ] Weight the review prompt based on complexity — more tool calls = deeper review
|
|
176
|
+
- [ ] Config: `nudgeToolCalls: number` (default: 15)
|
|
177
|
+
|
|
178
|
+
**Reference**: Hermes self-evaluation checkpoint described in [hermes-agent.ai skills blog](https://hermes-agent.ai/blog/hermes-agent-memory-system): "Every 15 tool calls, Hermes runs a self-evaluation checkpoint."
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## v0.3.0 — Session Search + Context Hardening
|
|
183
|
+
|
|
184
|
+
**Goal**: Add cross-session recall (Hermes L3) and security hardening via context fencing.
|
|
185
|
+
|
|
186
|
+
### Epic 5: Session Search
|
|
187
|
+
|
|
188
|
+
Hermes stores all conversations in SQLite with FTS5 full-text search. When it needs past context, it searches + summarizes. This transforms the extension from "2 files of notes" to "infinite searchable memory."
|
|
189
|
+
|
|
190
|
+
- [ ] Investigate Pi's `SessionManager` API for reading past session history
|
|
191
|
+
- [ ] Session indexer — index past and current session conversations for full-text search
|
|
192
|
+
- [ ] Storage: either a separate SQLite file (`~/.pi/agent/memory/sessions.db`) or leverage Pi's built-in session storage
|
|
193
|
+
- [ ] `session_search` tool — agent can query past conversations on demand
|
|
194
|
+
- [ ] Summarization via `pi.exec()` — summarize relevant session fragments to keep token cost manageable
|
|
195
|
+
- [ ] Config: `sessionSearchEnabled: boolean` (default: true)
|
|
196
|
+
- [ ] Config: `sessionRetentionDays: number` (default: 90)
|
|
197
|
+
|
|
198
|
+
**Reference**: Hermes `~/.hermes/state.db` with FTS5 indexing. See [Hermes Session Search docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory#session-search).
|
|
199
|
+
|
|
200
|
+
### Epic 6: Context Fencing + Memory Aging
|
|
201
|
+
|
|
202
|
+
- [ ] `<memory-context>` XML tags wrapping the system prompt injection — prevents the model from treating recalled memory as user discourse
|
|
203
|
+
- [ ] Memory aging — track last-referenced timestamp per entry, surface stale entries during consolidation
|
|
204
|
+
- [ ] Entry metadata — add optional `last_referenced` and `created_at` fields (stored in comments, transparent to § delimiter)
|
|
205
|
+
|
|
206
|
+
**Reference**: Hermes `MemoryManager.build_memory_context_block()` fencing with `<memory-context>` tags and "NOT new user input" system note.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## v0.4.0 — Structured Storage + Project Scoping
|
|
211
|
+
|
|
212
|
+
**Goal**: Replace flat markdown with SQLite backend. Add search. Add project-scoped memory. Keep the same tool interface.
|
|
213
|
+
|
|
214
|
+
### Core Abstraction
|
|
133
215
|
|
|
134
216
|
```typescript
|
|
135
217
|
interface MemoryBackend {
|
|
@@ -150,6 +232,18 @@ interface MemoryBackend {
|
|
|
150
232
|
|
|
151
233
|
Current `MemoryStore` becomes `MarkdownBackend` — the default, zero-dependency implementation. New `SQLiteBackend` adds structure without breaking anything.
|
|
152
234
|
|
|
235
|
+
### Onboarding: `/memory-interview`
|
|
236
|
+
|
|
237
|
+
New users install the extension and memory starts empty — the LLM has to learn preferences over many sessions through trial and error. The interview command solves this:
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
/memory-interview
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
The LLM asks 5-7 structured questions. Each answer is saved to `USER.md` via the existing content scanner. Users get immediate value on the very first session.
|
|
244
|
+
|
|
245
|
+
Inspired by [Honcho's `/honcho:interview`](https://docs.honcho.dev/v3/guides/integrations/claude-code#the-interview) pattern.
|
|
246
|
+
|
|
153
247
|
### Deliverables
|
|
154
248
|
|
|
155
249
|
- [ ] `MemoryBackend` interface in `src/types.ts`
|
|
@@ -159,7 +253,10 @@ Current `MemoryStore` becomes `MarkdownBackend` — the default, zero-dependency
|
|
|
159
253
|
- [ ] Project-scoped memory — entries tagged with `cwd`, injected when matching
|
|
160
254
|
- [ ] Context-aware injection — `formatForSystemPrompt(cwd, prompt)` filters by relevance
|
|
161
255
|
- [ ] Config: `"backend": "markdown" | "sqlite"` (defaults to `markdown` for zero-dep install)
|
|
162
|
-
- [ ] Migration tool:
|
|
256
|
+
- [ ] Migration tool: markdown → sqlite one-time import
|
|
257
|
+
- [ ] `/memory-interview` command — guided first-run interview that saves preferences to USER.md
|
|
258
|
+
- [ ] Interview prompt in `src/constants.ts` — structured questions with save instructions
|
|
259
|
+
- [ ] Content scanner validates interview answers (same as all writes)
|
|
163
260
|
|
|
164
261
|
### What Does NOT Change
|
|
165
262
|
|
|
@@ -170,38 +267,45 @@ Current `MemoryStore` becomes `MarkdownBackend` — the default, zero-dependency
|
|
|
170
267
|
|
|
171
268
|
---
|
|
172
269
|
|
|
173
|
-
## v0.
|
|
270
|
+
## v0.5.0 — External Sync
|
|
174
271
|
|
|
175
|
-
**Goal**:
|
|
272
|
+
**Goal**: Run a local backend (SQLite) as the source of truth, with optional external sync (Mem0 or Honcho) that mirrors writes and supplements search. Based on the [Hermes MemoryManager pattern](https://github.com/NousResearch/hermes-agent/blob/main/agent/memory_manager.py).
|
|
176
273
|
|
|
177
|
-
###
|
|
178
|
-
|
|
179
|
-
External memory services provide better semantic search, cross-session continuity, and multi-agent awareness. But they introduce trust boundaries — your agent's memories leave your machine. The content scanner becomes the security gate between Pi and any external service.
|
|
180
|
-
|
|
181
|
-
### Deliverables
|
|
182
|
-
|
|
183
|
-
- [ ] `Mem0Backend` — wraps Mem0's Node.js SDK (`add`, `search`, `update`, `delete`)
|
|
184
|
-
- [ ] `HonchoBackend` — wraps Honcho's API (`honcho_context`, `honcho_search_conclusions`, `honcho_reasoning`)
|
|
185
|
-
- [ ] Backend auto-detection — check for `MEM0_API_KEY` or `HONCHO_API_KEY` env vars, offer to configure
|
|
186
|
-
- [ ] Config: `"backend": "sqlite" | "mem0" | "honcho"` with `"mem0": { "apiKey": "...", "orgId": "..." }` options
|
|
187
|
-
- [ ] Selective injection by default when using external backends (leverage their search APIs)
|
|
188
|
-
- [ ] Offline fallback — if external backend is unreachable, fall back to local SQLite cache
|
|
189
|
-
- [ ] Data export — `memory export` command to dump all entries as JSON
|
|
190
|
-
|
|
191
|
-
### Security Model
|
|
274
|
+
### Architecture: Orchestrator + Sync Mirror
|
|
192
275
|
|
|
193
276
|
```
|
|
194
|
-
|
|
277
|
+
memory tool call (add/replace/remove/search)
|
|
195
278
|
↓
|
|
196
|
-
Content Scanner (
|
|
279
|
+
Content Scanner (always runs first, local)
|
|
197
280
|
↓ blocked? → return error to LLM
|
|
198
281
|
↓ passed
|
|
199
|
-
|
|
282
|
+
MemoryOrchestrator.write()
|
|
283
|
+
↓
|
|
284
|
+
├── BuiltinBackend.add() ← always runs (source of truth)
|
|
285
|
+
│
|
|
286
|
+
└── ExternalSync.onWrite() ← if configured (Mem0 or Honcho)
|
|
287
|
+
├── Mirror the write to external API
|
|
288
|
+
└── If external fails → log warning, don't block
|
|
289
|
+
|
|
290
|
+
MemoryOrchestrator.search()
|
|
200
291
|
↓
|
|
201
|
-
|
|
292
|
+
├── BuiltinBackend.search() ← always runs
|
|
293
|
+
└── ExternalSync.search() ← supplementary results (if configured)
|
|
294
|
+
↓
|
|
295
|
+
Merge + deduplicate → return to LLM
|
|
202
296
|
```
|
|
203
297
|
|
|
204
|
-
|
|
298
|
+
### Deliverables
|
|
299
|
+
|
|
300
|
+
- [ ] `MemoryOrchestrator` — wraps `MemoryBackend` + optional `ExternalSync`
|
|
301
|
+
- [ ] `ExternalSync` interface in `src/types.ts`
|
|
302
|
+
- [ ] `Mem0Sync` — implements `ExternalSync` using Mem0 Node.js SDK
|
|
303
|
+
- [ ] `HonchoSync` — implements `ExternalSync` using Honcho API
|
|
304
|
+
- [ ] `onWrite()` mirroring — builtin writes propagate to external sync
|
|
305
|
+
- [ ] One-external-only enforcement — same as Hermes, prevents conflicts
|
|
306
|
+
- [ ] Offline fallback — if external sync `isAvailable()` returns false, skip silently
|
|
307
|
+
- [ ] Config: `"externalSync": "mem0" | "honcho" | "none"` with credentials
|
|
308
|
+
- [ ] Data export — `memory export` command to dump all entries as JSON
|
|
205
309
|
|
|
206
310
|
---
|
|
207
311
|
|
|
@@ -216,7 +320,7 @@ The scanner runs **before** any backend. No adversarial content reaches external
|
|
|
216
320
|
- [ ] Multi-agent memory — shared context between agents, scoping rules (per-user, per-project, global)
|
|
217
321
|
- [ ] Extensible scanner rules — users can add custom patterns to the content scanner
|
|
218
322
|
- [ ] `/memory-insights` upgrade — show backend type, entry count, storage stats, last sync time
|
|
219
|
-
- [ ] Audit log — track all memory operations with timestamps
|
|
323
|
+
- [ ] Audit log — track all memory operations with timestamps
|
|
220
324
|
- [ ] Import/export — migrate between backends without data loss
|
|
221
325
|
- [ ] Benchmarks — context injection latency, search relevance, token budget utilization
|
|
222
326
|
|
|
@@ -232,6 +336,7 @@ These hold across all versions:
|
|
|
232
336
|
4. **Crash safety** — Atomic writes for markdown, WAL mode for SQLite, graceful degradation for external backends.
|
|
233
337
|
5. **Zero-config start** — Install and it works with sensible defaults. Configuration is for power users.
|
|
234
338
|
6. **Backwards compatible** — Every new version is a drop-in upgrade. No breaking changes to the tool interface or config format without a major version bump.
|
|
339
|
+
7. **Hermes-compatible data format** — `§` delimiter, MEMORY.md/USER.md structure, so users migrating from Hermes keep their data.
|
|
235
340
|
|
|
236
341
|
---
|
|
237
342
|
|
|
@@ -243,30 +348,35 @@ gantt
|
|
|
243
348
|
dateFormat YYYY-MM-DD
|
|
244
349
|
axisFormat %b %Y
|
|
245
350
|
|
|
246
|
-
section v0.1.0
|
|
247
|
-
Core memory + scanner + tool + review + flush :done, v01,
|
|
351
|
+
section v0.1.0 ✅
|
|
352
|
+
Core memory + scanner + tool + review + flush :done, v01, 2026-04-20, 5d
|
|
248
353
|
|
|
249
|
-
section v0.2.0
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
354
|
+
section v0.2.0 — Next
|
|
355
|
+
Skill tool + procedural memory :v02a, after v01, 5d
|
|
356
|
+
Auto-consolidation :v02b, after v02a, 3d
|
|
357
|
+
Correction detection + immediate save :v02c, after v02b, 3d
|
|
358
|
+
Tool-call-aware nudge :v02d, after v02c, 2d
|
|
254
359
|
|
|
255
360
|
section v0.3.0
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
361
|
+
Session search + indexer :v03a, after v02d, 7d
|
|
362
|
+
Context fencing + memory aging :v03b, after v03a, 3d
|
|
363
|
+
|
|
364
|
+
section v0.4.0
|
|
365
|
+
MemoryBackend interface + SQLite :v04a, after v03b, 7d
|
|
366
|
+
Project-scoped memory + interview :v04b, after v04a, 5d
|
|
367
|
+
|
|
368
|
+
section v0.5.0
|
|
369
|
+
ExternalSync + Mem0 / Honcho :v05a, after v04b, 10d
|
|
259
370
|
|
|
260
371
|
section v1.0.0
|
|
261
|
-
Smart consolidation + confidence :v1a, after
|
|
372
|
+
Smart consolidation + confidence :v1a, after v05a, 10d
|
|
262
373
|
Multi-agent memory + audit log :v1b, after v1a, 10d
|
|
263
|
-
Extensible scanner + benchmarks :v1c, after v1b, 7d
|
|
264
374
|
```
|
|
265
375
|
|
|
266
376
|
---
|
|
267
377
|
|
|
268
378
|
## How to Contribute
|
|
269
379
|
|
|
270
|
-
See [TASKS.md](0.1/TASKS.md) for current work. Pick an unchecked item, mark it `[~]`, implement, mark it `[x]` with the commit hash.
|
|
380
|
+
See [TASKS.md](0.1/TASKS.md) for current v0.1 work. Pick an unchecked item, mark it `[~]`, implement, mark it `[x]` with the commit hash.
|
|
271
381
|
|
|
272
|
-
For
|
|
382
|
+
For v0.2+ items, see [v0.2/TASKS.md](0.2/TASKS.md) once created. Open an issue with the version tag and describe what you want to work on.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-hermes-memory",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Your Pi agent remembers everything across sessions — your preferences, your stack, your corrections, and even how it solved problems. Zero-config install, works immediately. Persistent memory + procedural skills + auto-correction detection + security-first content scanning.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"files": [
|
|
@@ -17,17 +17,20 @@
|
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"check": "tsc --noEmit",
|
|
20
|
-
"test": "
|
|
20
|
+
"test": "tests/run-all.sh"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
23
23
|
"pi-package",
|
|
24
24
|
"pi-extension",
|
|
25
25
|
"memory",
|
|
26
|
+
"skills",
|
|
26
27
|
"learning-loop",
|
|
27
28
|
"agent",
|
|
28
29
|
"hermes",
|
|
29
30
|
"persistent-memory",
|
|
30
|
-
"content-scanner"
|
|
31
|
+
"content-scanner",
|
|
32
|
+
"correction-detection",
|
|
33
|
+
"auto-consolidation"
|
|
31
34
|
],
|
|
32
35
|
"license": "MIT",
|
|
33
36
|
"repository": {
|
|
@@ -35,11 +38,12 @@
|
|
|
35
38
|
"url": "https://github.com/chandra447/pi-hermes-memory"
|
|
36
39
|
},
|
|
37
40
|
"peerDependencies": {
|
|
38
|
-
"@mariozechner/pi-coding-agent": "
|
|
41
|
+
"@mariozechner/pi-coding-agent": ">=0.70.0"
|
|
39
42
|
},
|
|
40
43
|
"devDependencies": {
|
|
41
44
|
"@mariozechner/pi-ai": "^0.70.0",
|
|
42
45
|
"@mariozechner/pi-coding-agent": "^0.70.0",
|
|
46
|
+
"tsx": "^4.21.0",
|
|
43
47
|
"typebox": "^1.1.33",
|
|
44
48
|
"typescript": "^6.0.3"
|
|
45
49
|
}
|
package/src/config.ts
CHANGED
|
@@ -5,18 +5,24 @@ import type { MemoryConfig } from "./types.js";
|
|
|
5
5
|
import {
|
|
6
6
|
DEFAULT_MEMORY_CHAR_LIMIT,
|
|
7
7
|
DEFAULT_USER_CHAR_LIMIT,
|
|
8
|
+
DEFAULT_PROJECT_CHAR_LIMIT,
|
|
8
9
|
DEFAULT_NUDGE_INTERVAL,
|
|
9
10
|
DEFAULT_FLUSH_MIN_TURNS,
|
|
11
|
+
DEFAULT_NUDGE_TOOL_CALLS,
|
|
10
12
|
} from "./constants.js";
|
|
11
13
|
|
|
12
14
|
const DEFAULT_CONFIG: MemoryConfig = {
|
|
13
15
|
memoryCharLimit: DEFAULT_MEMORY_CHAR_LIMIT,
|
|
14
16
|
userCharLimit: DEFAULT_USER_CHAR_LIMIT,
|
|
17
|
+
projectCharLimit: DEFAULT_PROJECT_CHAR_LIMIT,
|
|
15
18
|
nudgeInterval: DEFAULT_NUDGE_INTERVAL,
|
|
16
19
|
reviewEnabled: true,
|
|
17
20
|
flushOnCompact: true,
|
|
18
21
|
flushOnShutdown: true,
|
|
19
22
|
flushMinTurns: DEFAULT_FLUSH_MIN_TURNS,
|
|
23
|
+
autoConsolidate: true,
|
|
24
|
+
correctionDetection: true,
|
|
25
|
+
nudgeToolCalls: DEFAULT_NUDGE_TOOL_CALLS,
|
|
20
26
|
};
|
|
21
27
|
|
|
22
28
|
export const DEFAULT_CONFIG_PATH = path.join(
|
|
@@ -40,6 +46,11 @@ export function loadConfig(): MemoryConfig {
|
|
|
40
46
|
if (typeof parsed.flushOnCompact === "boolean") config.flushOnCompact = parsed.flushOnCompact;
|
|
41
47
|
if (typeof parsed.flushOnShutdown === "boolean") config.flushOnShutdown = parsed.flushOnShutdown;
|
|
42
48
|
if (typeof parsed.flushMinTurns === "number") config.flushMinTurns = parsed.flushMinTurns;
|
|
49
|
+
if (typeof parsed.autoConsolidate === "boolean") config.autoConsolidate = parsed.autoConsolidate;
|
|
50
|
+
if (typeof parsed.correctionDetection === "boolean") config.correctionDetection = parsed.correctionDetection;
|
|
51
|
+
if (typeof parsed.nudgeToolCalls === "number") config.nudgeToolCalls = parsed.nudgeToolCalls;
|
|
52
|
+
if (typeof parsed.projectCharLimit === "number") config.projectCharLimit = parsed.projectCharLimit;
|
|
53
|
+
if (typeof parsed.memoryDir === "string") config.memoryDir = parsed.memoryDir;
|
|
43
54
|
return config;
|
|
44
55
|
}
|
|
45
56
|
} catch {
|