pi-hermes-memory 0.6.9 → 0.7.0
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 +48 -53
- package/docs/0.7/PLAN.md +349 -0
- package/docs/0.7/TASKS.md +110 -0
- package/docs/ROADMAP.md +55 -11
- package/docs/images/memory-architecture.svg +1 -1
- package/docs/images/session-lifecycle.svg +1 -1
- package/docs/mermaid/memory-architecture.mmd +15 -14
- package/docs/mermaid/session-lifecycle.mmd +7 -4
- package/package.json +2 -2
- package/src/config.ts +14 -0
- package/src/constants.ts +53 -1
- package/src/handlers/background-review.ts +5 -12
- package/src/handlers/learn-memory.ts +18 -10
- package/src/handlers/message-parts.ts +27 -0
- package/src/handlers/preview-context.ts +24 -3
- package/src/handlers/session-flush.ts +2 -11
- package/src/handlers/switch-project.ts +8 -6
- package/src/handlers/sync-markdown-memories.ts +8 -7
- package/src/index.ts +10 -16
- package/src/project.ts +3 -3
- package/src/prompt-context.ts +27 -0
- package/src/store/content-scanner.ts +1 -1
- package/src/store/memory-store.ts +9 -3
- package/src/store/skill-store.ts +7 -3
- package/src/types.ts +8 -0
- package/docs/0.7/TAGGED-SESSION-SKILL-REVIEW.md +0 -112
|
@@ -424,13 +424,19 @@ export class MemoryStore {
|
|
|
424
424
|
}
|
|
425
425
|
}
|
|
426
426
|
|
|
427
|
-
/**
|
|
427
|
+
/**
|
|
428
|
+
* Atomic write: temp file + fs.rename().
|
|
429
|
+
* Creates temp files in the same directory as the target to avoid
|
|
430
|
+
* cross-device rename errors (EXDEV) when os.tmpdir() is on a different
|
|
431
|
+
* drive than the memory directory (common on Windows).
|
|
432
|
+
*/
|
|
428
433
|
private async saveToDisk(target: "memory" | "user" | "failure"): Promise<void> {
|
|
429
434
|
const filePath = this.pathFor(target);
|
|
430
435
|
const entries = this.entriesFor(target);
|
|
431
436
|
const content = entries.length ? entries.join(ENTRY_DELIMITER) : "";
|
|
432
437
|
|
|
433
|
-
|
|
438
|
+
// Use the memory directory for temp files so rename stays on the same device
|
|
439
|
+
const tmpDir = await fs.mkdtemp(path.join(this.memoryDir, ".tmp-"));
|
|
434
440
|
const tmpPath = path.join(tmpDir, "write.tmp");
|
|
435
441
|
|
|
436
442
|
try {
|
|
@@ -440,7 +446,7 @@ export class MemoryStore {
|
|
|
440
446
|
try { await fs.unlink(tmpPath); } catch { /* ignore */ }
|
|
441
447
|
throw err;
|
|
442
448
|
} finally {
|
|
443
|
-
try { await fs.
|
|
449
|
+
try { await fs.rm(tmpDir, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
444
450
|
}
|
|
445
451
|
}
|
|
446
452
|
}
|
package/src/store/skill-store.ts
CHANGED
|
@@ -283,10 +283,14 @@ export class SkillStore {
|
|
|
283
283
|
|
|
284
284
|
// ─── Internal helpers ───
|
|
285
285
|
|
|
286
|
-
/**
|
|
286
|
+
/**
|
|
287
|
+
* Atomic write: temp file + rename.
|
|
288
|
+
* Creates temp files in the skills directory to avoid cross-device
|
|
289
|
+
* rename errors (EXDEV) on Windows when os.tmpdir() is on a different drive.
|
|
290
|
+
*/
|
|
287
291
|
private async atomicWrite(fileName: string, content: string): Promise<void> {
|
|
288
292
|
const filePath = path.join(this.skillsDir, fileName);
|
|
289
|
-
const tmpDir = await fs.mkdtemp(path.join(
|
|
293
|
+
const tmpDir = await fs.mkdtemp(path.join(this.skillsDir, ".tmp-"));
|
|
290
294
|
const tmpPath = path.join(tmpDir, "write.tmp");
|
|
291
295
|
|
|
292
296
|
try {
|
|
@@ -296,7 +300,7 @@ export class SkillStore {
|
|
|
296
300
|
try { await fs.unlink(tmpPath); } catch { /* ignore */ }
|
|
297
301
|
throw err;
|
|
298
302
|
} finally {
|
|
299
|
-
try { await fs.
|
|
303
|
+
try { await fs.rm(tmpDir, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
300
304
|
}
|
|
301
305
|
}
|
|
302
306
|
}
|
package/src/types.ts
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
import type { TextContent } from "@mariozechner/pi-ai";
|
|
6
6
|
|
|
7
7
|
export interface MemoryConfig {
|
|
8
|
+
/** Prompt memory mode. Default: policy-only */
|
|
9
|
+
memoryMode: "policy-only" | "legacy-inject";
|
|
8
10
|
/** Max chars for MEMORY.md (agent notes). Default: 5000 */
|
|
9
11
|
memoryCharLimit: number;
|
|
10
12
|
/** Max chars for USER.md (user profile). Default: 5000 */
|
|
@@ -13,6 +15,8 @@ export interface MemoryConfig {
|
|
|
13
15
|
projectCharLimit: number;
|
|
14
16
|
/** Turns between background auto-reviews. Default: 10 */
|
|
15
17
|
nudgeInterval: number;
|
|
18
|
+
/** Recent conversation messages included in background review. 0 = all. Default: 0 */
|
|
19
|
+
reviewRecentMessages?: number;
|
|
16
20
|
/** Enable background learning loop. Default: true */
|
|
17
21
|
reviewEnabled: boolean;
|
|
18
22
|
/** Flush memories before compaction. Default: true */
|
|
@@ -21,8 +25,12 @@ export interface MemoryConfig {
|
|
|
21
25
|
flushOnShutdown: boolean;
|
|
22
26
|
/** Minimum user turns before flush triggers. Default: 6 */
|
|
23
27
|
flushMinTurns: number;
|
|
28
|
+
/** Recent conversation messages included in session flush. 0 = all. Default: 0 */
|
|
29
|
+
flushRecentMessages?: number;
|
|
24
30
|
/** Override memory directory. Default: ~/.pi/agent/memory */
|
|
25
31
|
memoryDir?: string;
|
|
32
|
+
/** Directory for project-scoped memory (relative to ~/.pi/agent). Default: "projects-memory" */
|
|
33
|
+
projectsMemoryDir?: string;
|
|
26
34
|
/** Auto-consolidate when memory is full instead of returning error. Default: true */
|
|
27
35
|
autoConsolidate: boolean;
|
|
28
36
|
/** Detect user corrections and trigger immediate memory save. Default: true */
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# v0.7 Proposal: Tagged Session Review → Skill Creation
|
|
2
|
-
|
|
3
|
-
## Why
|
|
4
|
-
|
|
5
|
-
Community feedback highlighted a real gap:
|
|
6
|
-
- quick correction capture is useful,
|
|
7
|
-
- but **durable behavior should be promoted to skills intentionally**,
|
|
8
|
-
- and that flow should be reviewable in the TUI.
|
|
9
|
-
|
|
10
|
-
## Goal
|
|
11
|
-
|
|
12
|
-
Add a deterministic review workflow:
|
|
13
|
-
1. collect candidate learnings from session messages,
|
|
14
|
-
2. review them in a TUI modal,
|
|
15
|
-
3. promote selected items into a draft skill,
|
|
16
|
-
4. save via existing `skill` tool.
|
|
17
|
-
|
|
18
|
-
## Non-goals
|
|
19
|
-
|
|
20
|
-
- Auto-creating skills without user review.
|
|
21
|
-
- Replacing core memory entirely.
|
|
22
|
-
- Requiring git history for extraction.
|
|
23
|
-
|
|
24
|
-
## UX (Target)
|
|
25
|
-
|
|
26
|
-
### Command
|
|
27
|
-
- `/memory-review-candidates`
|
|
28
|
-
|
|
29
|
-
### Modal flow
|
|
30
|
-
1. **Candidate list** (tag, source session, snippet, confidence)
|
|
31
|
-
2. Actions per candidate: `approve`, `reject`, `edit`, `merge with...`
|
|
32
|
-
3. Multi-select candidates and choose `Create skill draft`
|
|
33
|
-
4. Draft editor with sections:
|
|
34
|
-
- `## When to Use`
|
|
35
|
-
- `## Procedure`
|
|
36
|
-
- `## Pitfalls`
|
|
37
|
-
- `## Verification`
|
|
38
|
-
5. Save with `skill.create`
|
|
39
|
-
|
|
40
|
-
## Candidate Sources
|
|
41
|
-
|
|
42
|
-
Priority order:
|
|
43
|
-
1. Explicit message tags from Pi sessions (when available)
|
|
44
|
-
2. Heuristic extraction from conversation patterns:
|
|
45
|
-
- repeated corrections,
|
|
46
|
-
- multi-step successful runs,
|
|
47
|
-
- repeated tool sequences,
|
|
48
|
-
- resolved failures with clear fix.
|
|
49
|
-
|
|
50
|
-
## Data Model (SQLite)
|
|
51
|
-
|
|
52
|
-
New table (proposal): `memory_candidates`
|
|
53
|
-
|
|
54
|
-
Columns:
|
|
55
|
-
- `id` INTEGER PK
|
|
56
|
-
- `session_id` TEXT
|
|
57
|
-
- `message_id` TEXT
|
|
58
|
-
- `project` TEXT
|
|
59
|
-
- `tag` TEXT
|
|
60
|
-
- `snippet` TEXT
|
|
61
|
-
- `rationale` TEXT
|
|
62
|
-
- `status` TEXT CHECK (`pending`,`approved`,`rejected`,`promoted`)
|
|
63
|
-
- `created_at` TEXT
|
|
64
|
-
- `updated_at` TEXT
|
|
65
|
-
- `promoted_skill` TEXT NULL
|
|
66
|
-
|
|
67
|
-
## Integration with Existing System
|
|
68
|
-
|
|
69
|
-
- Keep current memory + failure capture.
|
|
70
|
-
- Add a **promotion path** from memory/candidates to skills.
|
|
71
|
-
- Use existing `skill` tool as persistence layer.
|
|
72
|
-
- Use existing `session_search`/indexing infra for candidate discovery context.
|
|
73
|
-
|
|
74
|
-
## Rollout Plan
|
|
75
|
-
|
|
76
|
-
### Phase 1: Candidate staging (no modal)
|
|
77
|
-
- Create `memory_candidates` table
|
|
78
|
-
- Add extraction + `/memory-candidates` list command
|
|
79
|
-
- Add approve/reject commands
|
|
80
|
-
|
|
81
|
-
### Phase 2: TUI review modal
|
|
82
|
-
- Interactive candidate triage in one place
|
|
83
|
-
- Batch select + merge + edit
|
|
84
|
-
|
|
85
|
-
### Phase 3: Skill draft + save
|
|
86
|
-
- Generate skill draft from approved candidates
|
|
87
|
-
- Edit + save with `skill.create`
|
|
88
|
-
|
|
89
|
-
### Phase 4: Quality controls
|
|
90
|
-
- duplicate candidate suppression
|
|
91
|
-
- confidence thresholds
|
|
92
|
-
- weekly reminder: pending candidates review
|
|
93
|
-
|
|
94
|
-
## Success Criteria
|
|
95
|
-
|
|
96
|
-
- Lower noisy memory growth in `MEMORY.md`
|
|
97
|
-
- Higher percentage of reusable knowledge landing in `skills/`
|
|
98
|
-
- Fewer repeated correction loops across sessions
|
|
99
|
-
- Users report that learning feels intentional, not "whack-a-mole"
|
|
100
|
-
|
|
101
|
-
## Open Questions
|
|
102
|
-
|
|
103
|
-
1. Should candidates be extracted turn-by-turn or session-end only?
|
|
104
|
-
2. Should approved candidates auto-expire if not promoted in N days?
|
|
105
|
-
3. Should skill drafts include linked source message IDs for traceability?
|
|
106
|
-
4. Should project scope be default-on with optional cross-project merge mode?
|
|
107
|
-
|
|
108
|
-
## Notes
|
|
109
|
-
|
|
110
|
-
This proposal complements (not replaces) core memory.
|
|
111
|
-
Memory remains fast capture; skills remain durable procedure.
|
|
112
|
-
The new modal creates the missing bridge between them.
|