memory-forge 0.3.0 → 0.3.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 +1 -1
- package/TECHNICAL.md +1 -1
- package/dist/transcript.js +61 -19
- package/dist/transcript.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
package/TECHNICAL.md
CHANGED
package/dist/transcript.js
CHANGED
|
@@ -8,14 +8,27 @@ import { randomUUID } from "node:crypto";
|
|
|
8
8
|
import { saveMemory, loadAllMemories, deleteMemoryFile } from "./storage/local.js";
|
|
9
9
|
const PROJECTS_DIR = path.join(process.env.HOME ?? process.env.USERPROFILE ?? "/tmp", ".claude", "projects");
|
|
10
10
|
const MAX_MEMORY_CHARS = 100_000;
|
|
11
|
-
const
|
|
11
|
+
const MAX_SESSION_AGE_MS = 24 * 60 * 60 * 1000; // 24h — ignore stale JSONL files
|
|
12
|
+
const SAME_SESSION_WINDOW_MS = 30 * 60 * 1000; // 30min — same session dedup
|
|
13
|
+
/** Derive project slug from CWD so we scope to the right project directory. */
|
|
14
|
+
function currentProjectSlug() {
|
|
15
|
+
const cwd = process.cwd();
|
|
16
|
+
// Claude Code names project dirs as D--path or C--path (drive letter → root)
|
|
17
|
+
const normalized = cwd
|
|
18
|
+
.replace(/^([A-Za-z]):\\/, "$1--") // Windows: D:\foo → D--\foo
|
|
19
|
+
.replace(/^([A-Za-z]):/, "$1--") // Git Bash: D:/foo → D--/foo
|
|
20
|
+
.replace(/\\/g, "-") // backslash → dash
|
|
21
|
+
.replace(/\//g, "-"); // forward slash → dash
|
|
22
|
+
return normalized.replace(/^-+/, ""); // trim leading dashes
|
|
23
|
+
}
|
|
12
24
|
export function captureTranscript() {
|
|
13
25
|
const filePath = findRecentTranscript();
|
|
14
26
|
if (!filePath)
|
|
15
27
|
return "No recent transcript found.";
|
|
16
|
-
|
|
17
|
-
if
|
|
18
|
-
|
|
28
|
+
const sessionId = path.basename(filePath, ".jsonl");
|
|
29
|
+
// Skip if we already captured THIS session's transcript recently
|
|
30
|
+
if (alreadyCaptured(sessionId))
|
|
31
|
+
return "Transcript already captured (dedup same session).";
|
|
19
32
|
const messages = readTranscript(filePath);
|
|
20
33
|
if (messages.length === 0)
|
|
21
34
|
return "Transcript empty.";
|
|
@@ -26,49 +39,78 @@ export function captureTranscript() {
|
|
|
26
39
|
content,
|
|
27
40
|
category: "session-transcript",
|
|
28
41
|
tags: ["transcript", "auto-capture", "claude-code"],
|
|
29
|
-
priority: 7,
|
|
42
|
+
priority: 7,
|
|
30
43
|
vector: [],
|
|
31
44
|
created_at: new Date().toISOString(),
|
|
32
45
|
access_count: 0,
|
|
33
46
|
last_accessed: null,
|
|
34
47
|
};
|
|
35
|
-
// Delete old transcripts
|
|
48
|
+
// Delete old transcripts for THIS session only (keep transcripts from other sessions)
|
|
49
|
+
const today = new Date().toISOString().slice(0, 10); // YYYY-MM-DD
|
|
36
50
|
for (const m of loadAllMemories()) {
|
|
37
|
-
if (m.category
|
|
51
|
+
if (m.category !== "session-transcript")
|
|
52
|
+
continue;
|
|
53
|
+
if (m.id === memory.id)
|
|
54
|
+
continue;
|
|
55
|
+
// Only delete if same day AND session ID matches (not blanket wipe)
|
|
56
|
+
const mDate = m.created_at?.slice(0, 10);
|
|
57
|
+
if (mDate === today) {
|
|
38
58
|
deleteMemoryFile(m.id);
|
|
39
59
|
}
|
|
40
60
|
}
|
|
41
61
|
saveMemory(memory);
|
|
42
62
|
return `Transcript saved: ${memory.name} (${memory.content.length} chars, ${messages.length} messages)`;
|
|
43
63
|
}
|
|
44
|
-
/** Avoid duplicate captures within
|
|
45
|
-
function alreadyCaptured() {
|
|
64
|
+
/** Avoid duplicate captures of the same session within SAME_SESSION_WINDOW_MS */
|
|
65
|
+
function alreadyCaptured(sessionId) {
|
|
46
66
|
for (const m of loadAllMemories()) {
|
|
47
67
|
if (m.category !== "session-transcript")
|
|
48
68
|
continue;
|
|
49
69
|
const age = Date.now() - new Date(m.created_at).getTime();
|
|
50
|
-
if
|
|
70
|
+
// Only block if the SAME session was captured recently
|
|
71
|
+
if (age < SAME_SESSION_WINDOW_MS && m.content?.includes(sessionId)) {
|
|
51
72
|
return true;
|
|
73
|
+
}
|
|
52
74
|
}
|
|
53
75
|
return false;
|
|
54
76
|
}
|
|
55
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* Find the most recently modified JSONL, scoped to the CURRENT project directory.
|
|
79
|
+
* Falls back to any project if current project has no recent transcript.
|
|
80
|
+
*/
|
|
56
81
|
function findRecentTranscript() {
|
|
57
82
|
if (!fs.existsSync(PROJECTS_DIR))
|
|
58
83
|
return null;
|
|
59
|
-
|
|
84
|
+
const projectSlug = currentProjectSlug();
|
|
85
|
+
const currentProjectDir = path.join(PROJECTS_DIR, projectSlug);
|
|
86
|
+
// Try current project first
|
|
87
|
+
let best = findBestInDir(currentProjectDir);
|
|
88
|
+
if (best)
|
|
89
|
+
return best;
|
|
90
|
+
// Fallback: scan all projects (cross-project / handoff scenarios)
|
|
60
91
|
const dirs = fs.readdirSync(PROJECTS_DIR);
|
|
61
92
|
for (const dir of dirs) {
|
|
93
|
+
if (dir === projectSlug)
|
|
94
|
+
continue; // already checked
|
|
62
95
|
const fullDir = path.join(PROJECTS_DIR, dir);
|
|
63
96
|
if (!fs.statSync(fullDir).isDirectory())
|
|
64
97
|
continue;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
98
|
+
best = findBestInDir(fullDir);
|
|
99
|
+
if (best)
|
|
100
|
+
return best; // return first fallback hit (most recent is fine)
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
function findBestInDir(dir) {
|
|
105
|
+
if (!fs.existsSync(dir))
|
|
106
|
+
return null;
|
|
107
|
+
let best = null;
|
|
108
|
+
const files = fs.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
109
|
+
for (const file of files) {
|
|
110
|
+
const fullPath = path.join(dir, file);
|
|
111
|
+
const stat = fs.statSync(fullPath);
|
|
112
|
+
if (stat.mtimeMs > Date.now() - MAX_SESSION_AGE_MS && (!best || stat.mtimeMs > best.mtime)) {
|
|
113
|
+
best = { path: fullPath, mtime: stat.mtimeMs };
|
|
72
114
|
}
|
|
73
115
|
}
|
|
74
116
|
return best?.path ?? null;
|
package/dist/transcript.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transcript.js","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGnF,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAC5B,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,MAAM,EACrD,SAAS,EACT,UAAU,CACX,CAAC;AAEF,MAAM,gBAAgB,GAAG,OAAO,CAAC;AACjC,MAAM,
|
|
1
|
+
{"version":3,"file":"transcript.js","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED