@bubstack/moe-memory 0.1.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.
Files changed (157) hide show
  1. package/.mcp.json +18 -0
  2. package/README.md +47 -0
  3. package/agents/search-conversations.md +171 -0
  4. package/dist/LICENSE +25 -0
  5. package/dist/cli.d.ts +25 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +125 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/codex-hook-trust.d.ts +4 -0
  10. package/dist/codex-hook-trust.d.ts.map +1 -0
  11. package/dist/codex-hook-trust.js +114 -0
  12. package/dist/codex-hook-trust.js.map +1 -0
  13. package/dist/codex-support.d.ts +6 -0
  14. package/dist/codex-support.d.ts.map +1 -0
  15. package/dist/codex-support.js +29 -0
  16. package/dist/codex-support.js.map +1 -0
  17. package/dist/constants.d.ts +14 -0
  18. package/dist/constants.d.ts.map +1 -0
  19. package/dist/constants.js +14 -0
  20. package/dist/constants.js.map +1 -0
  21. package/dist/db.d.ts +103 -0
  22. package/dist/db.d.ts.map +1 -0
  23. package/dist/db.js +430 -0
  24. package/dist/db.js.map +1 -0
  25. package/dist/doctor-cli.d.ts +3 -0
  26. package/dist/doctor-cli.d.ts.map +1 -0
  27. package/dist/doctor-cli.js +43 -0
  28. package/dist/doctor-cli.js.map +1 -0
  29. package/dist/doctor.d.ts +17 -0
  30. package/dist/doctor.d.ts.map +1 -0
  31. package/dist/doctor.js +98 -0
  32. package/dist/doctor.js.map +1 -0
  33. package/dist/embedding-migration.d.ts +73 -0
  34. package/dist/embedding-migration.d.ts.map +1 -0
  35. package/dist/embedding-migration.js +120 -0
  36. package/dist/embedding-migration.js.map +1 -0
  37. package/dist/embeddings.d.ts +78 -0
  38. package/dist/embeddings.d.ts.map +1 -0
  39. package/dist/embeddings.js +180 -0
  40. package/dist/embeddings.js.map +1 -0
  41. package/dist/file-lock.d.ts +39 -0
  42. package/dist/file-lock.d.ts.map +1 -0
  43. package/dist/file-lock.js +91 -0
  44. package/dist/file-lock.js.map +1 -0
  45. package/dist/index-cli.d.ts +10 -0
  46. package/dist/index-cli.d.ts.map +1 -0
  47. package/dist/index-cli.js +195 -0
  48. package/dist/index-cli.js.map +1 -0
  49. package/dist/index.d.ts +12 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +19 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/indexer.d.ts +4 -0
  54. package/dist/indexer.d.ts.map +1 -0
  55. package/dist/indexer.js +318 -0
  56. package/dist/indexer.js.map +1 -0
  57. package/dist/install-check.d.ts +48 -0
  58. package/dist/install-check.d.ts.map +1 -0
  59. package/dist/install-check.js +82 -0
  60. package/dist/install-check.js.map +1 -0
  61. package/dist/journal/index.d.ts +5 -0
  62. package/dist/journal/index.d.ts.map +1 -0
  63. package/dist/journal/index.js +5 -0
  64. package/dist/journal/index.js.map +1 -0
  65. package/dist/journal/legacy-sidecars.d.ts +74 -0
  66. package/dist/journal/legacy-sidecars.d.ts.map +1 -0
  67. package/dist/journal/legacy-sidecars.js +151 -0
  68. package/dist/journal/legacy-sidecars.js.map +1 -0
  69. package/dist/journal/markdown.d.ts +91 -0
  70. package/dist/journal/markdown.d.ts.map +1 -0
  71. package/dist/journal/markdown.js +234 -0
  72. package/dist/journal/markdown.js.map +1 -0
  73. package/dist/journal/search.d.ts +91 -0
  74. package/dist/journal/search.d.ts.map +1 -0
  75. package/dist/journal/search.js +203 -0
  76. package/dist/journal/search.js.map +1 -0
  77. package/dist/journal/store.d.ts +96 -0
  78. package/dist/journal/store.d.ts.map +1 -0
  79. package/dist/journal/store.js +270 -0
  80. package/dist/journal/store.js.map +1 -0
  81. package/dist/journal-cli.d.ts +19 -0
  82. package/dist/journal-cli.d.ts.map +1 -0
  83. package/dist/journal-cli.js +153 -0
  84. package/dist/journal-cli.js.map +1 -0
  85. package/dist/logging.d.ts +6 -0
  86. package/dist/logging.d.ts.map +1 -0
  87. package/dist/logging.js +20 -0
  88. package/dist/logging.js.map +1 -0
  89. package/dist/mcp-server.d.ts +34 -0
  90. package/dist/mcp-server.d.ts.map +1 -0
  91. package/dist/mcp-server.js +607 -0
  92. package/dist/mcp-server.js.map +1 -0
  93. package/dist/parser.d.ts +11 -0
  94. package/dist/parser.d.ts.map +1 -0
  95. package/dist/parser.js +445 -0
  96. package/dist/parser.js.map +1 -0
  97. package/dist/paths.d.ts +103 -0
  98. package/dist/paths.d.ts.map +1 -0
  99. package/dist/paths.js +258 -0
  100. package/dist/paths.js.map +1 -0
  101. package/dist/search-cli.d.ts +3 -0
  102. package/dist/search-cli.d.ts.map +1 -0
  103. package/dist/search-cli.js +138 -0
  104. package/dist/search-cli.js.map +1 -0
  105. package/dist/search.d.ts +36 -0
  106. package/dist/search.d.ts.map +1 -0
  107. package/dist/search.js +371 -0
  108. package/dist/search.js.map +1 -0
  109. package/dist/show-cli.d.ts +3 -0
  110. package/dist/show-cli.d.ts.map +1 -0
  111. package/dist/show-cli.js +60 -0
  112. package/dist/show-cli.js.map +1 -0
  113. package/dist/show.d.ts +3 -0
  114. package/dist/show.d.ts.map +1 -0
  115. package/dist/show.js +984 -0
  116. package/dist/show.js.map +1 -0
  117. package/dist/stats-cli.d.ts +3 -0
  118. package/dist/stats-cli.d.ts.map +1 -0
  119. package/dist/stats-cli.js +51 -0
  120. package/dist/stats-cli.js.map +1 -0
  121. package/dist/stats.d.ts +19 -0
  122. package/dist/stats.d.ts.map +1 -0
  123. package/dist/stats.js +116 -0
  124. package/dist/stats.js.map +1 -0
  125. package/dist/summarizer.d.ts +83 -0
  126. package/dist/summarizer.d.ts.map +1 -0
  127. package/dist/summarizer.js +526 -0
  128. package/dist/summarizer.js.map +1 -0
  129. package/dist/summary-sentinel.d.ts +31 -0
  130. package/dist/summary-sentinel.d.ts.map +1 -0
  131. package/dist/summary-sentinel.js +80 -0
  132. package/dist/summary-sentinel.js.map +1 -0
  133. package/dist/sync-cli.d.ts +15 -0
  134. package/dist/sync-cli.d.ts.map +1 -0
  135. package/dist/sync-cli.js +202 -0
  136. package/dist/sync-cli.js.map +1 -0
  137. package/dist/sync.d.ts +35 -0
  138. package/dist/sync.d.ts.map +1 -0
  139. package/dist/sync.js +204 -0
  140. package/dist/sync.js.map +1 -0
  141. package/dist/types.d.ts +125 -0
  142. package/dist/types.d.ts.map +1 -0
  143. package/dist/types.js +32 -0
  144. package/dist/types.js.map +1 -0
  145. package/dist/verify.d.ts +30 -0
  146. package/dist/verify.d.ts.map +1 -0
  147. package/dist/verify.js +174 -0
  148. package/dist/verify.js.map +1 -0
  149. package/dist/version.d.ts +13 -0
  150. package/dist/version.d.ts.map +1 -0
  151. package/dist/version.js +13 -0
  152. package/dist/version.js.map +1 -0
  153. package/hooks/hooks.json +15 -0
  154. package/package.json +71 -0
  155. package/prompts/search-agent.md +160 -0
  156. package/skills/remembering-conversations/MCP-TOOLS.md +147 -0
  157. package/skills/remembering-conversations/SKILL.md +97 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary-sentinel.js","sourceRoot":"","sources":["../src/summary-sentinel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC;AAC1C,MAAM,mBAAmB,GAAG,GAAG,YAAY,IAAI,CAAC;AAChD,MAAM,gBAAgB,GAAG,QAAQ,CAAC,CAAC,SAAS;AAE5C,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,GAAG,YAAY,KAAK,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,OAAO,IAAI,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,OAAO,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,eAAe;IACtB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC;IAC7D,IAAI,CAAC,GAAG;QAAE,OAAO,gBAAgB,CAAC;IAClC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC9B,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC;AACnF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,WAAmB;IAChD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9C,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,iBAAiB,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAmB;IACvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,IAAI,eAAe,EAAE,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `moe-memory sync` — copy new transcripts into the archive, index them, then
3
+ * run one batch of the embedding migration.
4
+ *
5
+ * Was a standalone script executed by `cli/episodic-memory.js` through
6
+ * `spawn(node, join(__dirname, '../dist/sync-cli.js'))`. It is a function now
7
+ * and `src/cli.ts` calls it in-process: there is one bin, it compiles to
8
+ * `dist/cli.js`, and every `../dist/` prefix in the old shim layer was a
9
+ * resolution that only worked from the right directory.
10
+ */
11
+ /**
12
+ * Exit code, so the dispatcher can propagate it. `null` means "keep going".
13
+ */
14
+ export declare function runSync(args: string[]): Promise<number>;
15
+ //# sourceMappingURL=sync-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-cli.d.ts","sourceRoot":"","sources":["../src/sync-cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA4EH;;GAEG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4I7D"}
@@ -0,0 +1,202 @@
1
+ /**
2
+ * `moe-memory sync` — copy new transcripts into the archive, index them, then
3
+ * run one batch of the embedding migration.
4
+ *
5
+ * Was a standalone script executed by `cli/episodic-memory.js` through
6
+ * `spawn(node, join(__dirname, '../dist/sync-cli.js'))`. It is a function now
7
+ * and `src/cli.ts` calls it in-process: there is one bin, it compiles to
8
+ * `dist/cli.js`, and every `../dist/` prefix in the old shim layer was a
9
+ * resolution that only worked from the right directory.
10
+ */
11
+ import { spawn } from "node:child_process";
12
+ import fs from "node:fs";
13
+ import path from "node:path";
14
+ import { initDatabase } from "./db.js";
15
+ import { countStale, runMigrationBatch } from "./embedding-migration.js";
16
+ import { generateExchangeEmbedding, initEmbeddings } from "./embeddings.js";
17
+ import { acquireFileLock, readLockHolder, releaseFileLock } from "./file-lock.js";
18
+ import { formatLogLine, getSyncLogPath } from "./logging.js";
19
+ import { getArchiveDir, getConversationSourceDirs, getIndexDir } from "./paths.js";
20
+ import { shouldSkipReentrantSync } from "./summarizer.js";
21
+ import { syncConversations } from "./sync.js";
22
+ const HELP = `
23
+ Usage: moe-memory sync [--background]
24
+
25
+ Sync conversations from Claude Code and Codex transcript directories to archive and index them.
26
+
27
+ This command:
28
+ 1. Copies new or updated .jsonl files to conversation archive
29
+ 2. Generates embeddings for semantic search
30
+ 3. Updates the search index
31
+
32
+ Only processes files that are new or have been modified since last sync.
33
+ Safe to run multiple times - subsequent runs are fast no-ops.
34
+
35
+ OPTIONS:
36
+ --background Run sync in background (for hooks, returns immediately)
37
+
38
+ EXAMPLES:
39
+ # Sync all new conversations
40
+ moe-memory sync
41
+
42
+ # Sync in background (for hooks)
43
+ moe-memory sync --background
44
+
45
+ # Use in a Claude Code SessionStart hook
46
+ moe-memory sync --background
47
+ `;
48
+ const MIGRATION_BATCH_SIZE = Number.parseInt(process.env.MOE_MEMORY_MIGRATION_BATCH || "500", 10);
49
+ async function runEmbeddingMigrationPhase() {
50
+ const db = initDatabase();
51
+ try {
52
+ const stale = countStale(db);
53
+ if (stale === 0)
54
+ return;
55
+ console.error(`\nmoe-memory: ${stale} exchange(s) on the old embedding model — migrating up to ${MIGRATION_BATCH_SIZE} this run`);
56
+ await initEmbeddings();
57
+ const indexDir = getIndexDir();
58
+ const done = await runMigrationBatch(db, indexDir, MIGRATION_BATCH_SIZE, generateExchangeEmbedding);
59
+ if (done > 0) {
60
+ const after = countStale(db);
61
+ console.error(`moe-memory: re-embedded ${done} (${after} still stale; will resume on next sync)`);
62
+ }
63
+ }
64
+ catch (err) {
65
+ console.error("moe-memory: migration phase error:", err instanceof Error ? err.message : String(err));
66
+ }
67
+ finally {
68
+ db.close();
69
+ }
70
+ }
71
+ /**
72
+ * Exit code, so the dispatcher can propagate it. `null` means "keep going".
73
+ */
74
+ export async function runSync(args) {
75
+ // Reentrancy guard (#87): if this sync was triggered by a SessionStart hook
76
+ // inside a Claude subprocess that the summarizer just spawned, exit silently.
77
+ // Without this, summarization spawns a Claude subprocess which fires
78
+ // SessionStart which runs sync which spawns more summarization — cascading
79
+ // fanout that pegs CPU and burns API quota.
80
+ if (shouldSkipReentrantSync()) {
81
+ // stderr keeps the message out of any stdout consumers (e.g., MCP)
82
+ // while still being visible in hook logs.
83
+ console.error("moe-memory: skipping sync inside summarizer-spawned subprocess (#87)");
84
+ return 0;
85
+ }
86
+ if (args.includes("--help") || args.includes("-h")) {
87
+ console.log(HELP);
88
+ return 0;
89
+ }
90
+ // If background mode, fork the process and return immediately.
91
+ if (args.includes("--background")) {
92
+ const filteredArgs = args.filter((arg) => arg !== "--background");
93
+ const logPath = getSyncLogPath();
94
+ const logFd = fs.openSync(logPath, "a");
95
+ fs.writeSync(logFd, formatLogLine("info", `Starting background sync from pid ${process.pid}`));
96
+ // Re-spawn this same entry point with the `sync` subcommand. argv[1] is the
97
+ // dispatcher (dist/cli.js, or the bin symlink pointing at it); passing the
98
+ // subcommand back explicitly is what makes that safe under one bin.
99
+ const entry = process.argv[1];
100
+ if (!entry) {
101
+ console.error("moe-memory: cannot determine own entry point; running sync in foreground");
102
+ }
103
+ else {
104
+ const child = spawn(process.execPath, [entry, "sync", ...filteredArgs], {
105
+ detached: true,
106
+ stdio: ["ignore", logFd, logFd],
107
+ });
108
+ child.unref(); // Allow parent to exit
109
+ console.log(`Sync started in background. Log: ${logPath}`);
110
+ return 0;
111
+ }
112
+ }
113
+ const sourceDirs = getConversationSourceDirs();
114
+ const destDir = getArchiveDir();
115
+ if (sourceDirs.length === 0) {
116
+ console.log("⚠️ No conversation source directories found.");
117
+ console.log(" Checked: ~/.claude/projects, ~/.claude/transcripts, and ~/.codex/sessions");
118
+ if (process.env.CLAUDE_CONFIG_DIR) {
119
+ console.log(` CLAUDE_CONFIG_DIR is set to: ${process.env.CLAUDE_CONFIG_DIR}`);
120
+ }
121
+ return 0;
122
+ }
123
+ // Single-instance lock (#97). Independent SessionStart events from multiple
124
+ // Claude Code sessions each fire `sync --background`; without a lock they race
125
+ // the SQLite write path and pile up Claude subprocesses for summarization. On
126
+ // Windows the latter exhausts the desktop heap and crashes the workers with
127
+ // STATUS_DLL_INIT_FAILED. Acquire after the source-dir check so help/version
128
+ // paths don't touch the filesystem unnecessarily, and release on every exit.
129
+ const syncLockPath = path.join(path.dirname(getSyncLogPath()), "moe-memory-sync.lock");
130
+ const syncLock = acquireFileLock(syncLockPath);
131
+ if (!syncLock) {
132
+ const holder = readLockHolder(syncLockPath);
133
+ const holderLabel = holder !== null ? `pid ${holder}` : "another process";
134
+ console.error(`moe-memory: sync already running (${holderLabel}); skipping`);
135
+ return 0;
136
+ }
137
+ let released = false;
138
+ const releaseSyncLockOnce = () => {
139
+ if (released)
140
+ return;
141
+ released = true;
142
+ releaseFileLock(syncLock);
143
+ };
144
+ process.on("exit", releaseSyncLockOnce);
145
+ process.on("SIGINT", () => {
146
+ releaseSyncLockOnce();
147
+ process.exit(130);
148
+ });
149
+ process.on("SIGTERM", () => {
150
+ releaseSyncLockOnce();
151
+ process.exit(143);
152
+ });
153
+ process.on("SIGHUP", () => {
154
+ releaseSyncLockOnce();
155
+ process.exit(129);
156
+ });
157
+ console.log("Syncing conversations...");
158
+ console.log(`Sources: ${sourceDirs.join(", ")}`);
159
+ console.log(`Destination: ${destDir}\n`);
160
+ const totals = {
161
+ copied: 0,
162
+ skipped: 0,
163
+ indexed: 0,
164
+ summarized: 0,
165
+ errors: [],
166
+ };
167
+ try {
168
+ for (const sourceDir of sourceDirs) {
169
+ const result = await syncConversations(sourceDir, destDir);
170
+ totals.copied += result.copied;
171
+ totals.skipped += result.skipped;
172
+ totals.indexed += result.indexed;
173
+ totals.summarized += result.summarized;
174
+ totals.errors.push(...result.errors);
175
+ }
176
+ console.log("\n✅ Sync complete!");
177
+ console.log(` Copied: ${totals.copied}`);
178
+ console.log(` Skipped: ${totals.skipped}`);
179
+ console.log(` Indexed: ${totals.indexed}`);
180
+ console.log(` Summarized: ${totals.summarized}`);
181
+ if (totals.errors.length > 0) {
182
+ console.log(`\n⚠️ Errors: ${totals.errors.length}`);
183
+ for (const err of totals.errors)
184
+ console.log(` ${err.file}: ${err.error}`);
185
+ // Help diagnose silent summarization failures (#70)
186
+ const summaryErrors = totals.errors.filter((e) => e.error.startsWith("Summary generation failed"));
187
+ if (summaryErrors.length > 0 && totals.summarized === 0) {
188
+ console.log(`\n💡 All ${summaryErrors.length} summarization attempts failed.`);
189
+ console.log(" Check your API configuration (MOE_MEMORY_API_BASE_URL / ANTHROPIC_API_KEY).");
190
+ }
191
+ }
192
+ // After regular sync, do a batch of embedding migration if any rows are
193
+ // still on the old encoder. Lock-protected; if another process is already
194
+ // migrating, this is a no-op.
195
+ await runEmbeddingMigrationPhase();
196
+ return 0;
197
+ }
198
+ finally {
199
+ releaseSyncLockOnce();
200
+ }
201
+ }
202
+ //# sourceMappingURL=sync-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-cli.js","sourceRoot":"","sources":["../src/sync-cli.ts"],"names":[],"mappings":"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"}
package/dist/sync.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The in-transcript opt-out a user types to keep a conversation out of the index.
3
+ *
4
+ * ⚠️ HIGHEST-RISK RENAME IN THE PACKAGE, and the reason BOTH forms are here
5
+ * permanently. This is a marker people have already typed into transcripts
6
+ * sitting on disk. Renaming it and dropping the old form does not fail loudly —
7
+ * it silently starts indexing every conversation a user had explicitly marked
8
+ * DO-NOT-INDEX. So the upstream marker is honoured forever; it is data, not a
9
+ * brand token, and Zone B reasoning applies to it even though it lives in Zone A
10
+ * code.
11
+ */
12
+ export declare const EXCLUSION_MARKER = "<INSTRUCTIONS-TO-MOE-MEMORY>DO NOT INDEX THIS CHAT</INSTRUCTIONS-TO-MOE-MEMORY>";
13
+ /** The upstream form. Accepted permanently — see EXCLUSION_MARKER. */
14
+ export declare const LEGACY_EXCLUSION_MARKER = "<INSTRUCTIONS-TO-EPISODIC-MEMORY>DO NOT INDEX THIS CHAT</INSTRUCTIONS-TO-EPISODIC-MEMORY>";
15
+ export declare const EXCLUSION_MARKERS: string[];
16
+ /** True when a transcript carries any marker that keeps it out of the index. */
17
+ export declare function shouldSkipConversation(filePath: string): boolean;
18
+ export interface SyncResult {
19
+ copied: number;
20
+ skipped: number;
21
+ indexed: number;
22
+ summarized: number;
23
+ errors: Array<{
24
+ file: string;
25
+ error: string;
26
+ }>;
27
+ }
28
+ export interface SyncOptions {
29
+ skipIndex?: boolean;
30
+ skipSummaries?: boolean;
31
+ summaryLimit?: number;
32
+ }
33
+ export declare function extractSessionIdFromPath(filePath: string): string | null;
34
+ export declare function syncConversations(sourceDir: string, destDir: string, options?: SyncOptions): Promise<SyncResult>;
35
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,oFACsD,CAAC;AAEpF,sEAAsE;AACtE,eAAO,MAAM,uBAAuB,8FACyD,CAAC;AAE9F,eAAO,MAAM,iBAAiB,UAK7B,CAAC;AAEF,gFAAgF;AAChF,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQhE;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAyBD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMxE;AAED,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAkKrB"}
package/dist/sync.js ADDED
@@ -0,0 +1,204 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { SUMMARIZER_CONTEXT_MARKER } from "./constants.js";
4
+ import { findJsonlFiles, getExcludedProjects } from "./paths.js";
5
+ import { formatErrorSentinel, shouldQueueForSummary } from "./summary-sentinel.js";
6
+ /**
7
+ * The in-transcript opt-out a user types to keep a conversation out of the index.
8
+ *
9
+ * ⚠️ HIGHEST-RISK RENAME IN THE PACKAGE, and the reason BOTH forms are here
10
+ * permanently. This is a marker people have already typed into transcripts
11
+ * sitting on disk. Renaming it and dropping the old form does not fail loudly —
12
+ * it silently starts indexing every conversation a user had explicitly marked
13
+ * DO-NOT-INDEX. So the upstream marker is honoured forever; it is data, not a
14
+ * brand token, and Zone B reasoning applies to it even though it lives in Zone A
15
+ * code.
16
+ */
17
+ export const EXCLUSION_MARKER = "<INSTRUCTIONS-TO-MOE-MEMORY>DO NOT INDEX THIS CHAT</INSTRUCTIONS-TO-MOE-MEMORY>";
18
+ /** The upstream form. Accepted permanently — see EXCLUSION_MARKER. */
19
+ export const LEGACY_EXCLUSION_MARKER = "<INSTRUCTIONS-TO-EPISODIC-MEMORY>DO NOT INDEX THIS CHAT</INSTRUCTIONS-TO-EPISODIC-MEMORY>";
20
+ export const EXCLUSION_MARKERS = [
21
+ EXCLUSION_MARKER,
22
+ LEGACY_EXCLUSION_MARKER,
23
+ "Only use NO_INSIGHTS_FOUND",
24
+ SUMMARIZER_CONTEXT_MARKER,
25
+ ];
26
+ /** True when a transcript carries any marker that keeps it out of the index. */
27
+ export function shouldSkipConversation(filePath) {
28
+ try {
29
+ const content = fs.readFileSync(filePath, "utf-8");
30
+ return EXCLUSION_MARKERS.some((marker) => content.includes(marker));
31
+ }
32
+ catch {
33
+ // If we can't read the file, don't skip it
34
+ return false;
35
+ }
36
+ }
37
+ function copyIfNewer(src, dest) {
38
+ // Ensure destination directory exists
39
+ const destDir = path.dirname(dest);
40
+ if (!fs.existsSync(destDir)) {
41
+ fs.mkdirSync(destDir, { recursive: true });
42
+ }
43
+ // Check if destination exists and is up-to-date
44
+ if (fs.existsSync(dest)) {
45
+ const srcStat = fs.statSync(src);
46
+ const destStat = fs.statSync(dest);
47
+ if (destStat.mtimeMs >= srcStat.mtimeMs) {
48
+ return false; // Dest is current, skip
49
+ }
50
+ }
51
+ // Atomic copy: temp file + rename
52
+ const tempDest = `${dest}.tmp.${process.pid}`;
53
+ fs.copyFileSync(src, tempDest);
54
+ fs.renameSync(tempDest, dest); // Atomic on same filesystem
55
+ return true;
56
+ }
57
+ export function extractSessionIdFromPath(filePath) {
58
+ // Extract session ID from Claude filename or Codex rollout filename.
59
+ const basename = path.basename(filePath, ".jsonl");
60
+ const uuidPattern = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi;
61
+ const matches = basename.match(uuidPattern);
62
+ return matches?.[matches.length - 1] ?? null;
63
+ }
64
+ export async function syncConversations(sourceDir, destDir, options = {}) {
65
+ const result = {
66
+ copied: 0,
67
+ skipped: 0,
68
+ indexed: 0,
69
+ summarized: 0,
70
+ errors: [],
71
+ };
72
+ // Ensure source directory exists
73
+ if (!fs.existsSync(sourceDir)) {
74
+ return result;
75
+ }
76
+ // Collect files to index and summarize
77
+ const filesToIndex = [];
78
+ const filesToSummarize = [];
79
+ // Walk source directory
80
+ const projects = fs.readdirSync(sourceDir);
81
+ const excludedProjects = getExcludedProjects();
82
+ const excludedDirSet = new Set(excludedProjects);
83
+ for (const project of projects) {
84
+ if (excludedProjects.includes(project)) {
85
+ console.log(`\nSkipping excluded project: ${project}`);
86
+ continue;
87
+ }
88
+ const projectPath = path.join(sourceDir, project);
89
+ const stat = fs.statSync(projectPath);
90
+ if (!stat.isDirectory())
91
+ continue;
92
+ const files = findJsonlFiles(projectPath, excludedDirSet);
93
+ for (const file of files) {
94
+ const srcFile = path.join(projectPath, file);
95
+ const destFile = path.join(destDir, project, file);
96
+ try {
97
+ const wasCopied = copyIfNewer(srcFile, destFile);
98
+ if (wasCopied) {
99
+ result.copied++;
100
+ filesToIndex.push(destFile);
101
+ }
102
+ else {
103
+ result.skipped++;
104
+ }
105
+ // Check if this file needs a summary (whether newly copied or existing).
106
+ // shouldQueueForSummary skips files that already have a real summary or
107
+ // an empty zero-exchange sentinel, and retries stale error sentinels (#96).
108
+ if (!options.skipSummaries) {
109
+ const summaryPath = destFile.replace(".jsonl", "-summary.txt");
110
+ if (shouldQueueForSummary(summaryPath) && !shouldSkipConversation(destFile)) {
111
+ const sessionId = extractSessionIdFromPath(destFile);
112
+ if (sessionId) {
113
+ filesToSummarize.push({ path: destFile, sessionId });
114
+ }
115
+ }
116
+ }
117
+ }
118
+ catch (error) {
119
+ result.errors.push({
120
+ file: srcFile,
121
+ error: error instanceof Error ? error.message : String(error),
122
+ });
123
+ }
124
+ }
125
+ }
126
+ // Index copied files (unless skipIndex is set)
127
+ if (!options.skipIndex && filesToIndex.length > 0) {
128
+ const { initDatabase, insertExchange } = await import("./db.js");
129
+ const { initEmbeddings, generateExchangeEmbedding } = await import("./embeddings.js");
130
+ const { parseConversation } = await import("./parser.js");
131
+ const db = initDatabase();
132
+ await initEmbeddings();
133
+ for (const file of filesToIndex) {
134
+ try {
135
+ // Check for DO NOT INDEX marker
136
+ if (shouldSkipConversation(file)) {
137
+ continue; // Skip indexing but file is already copied
138
+ }
139
+ const project = path.basename(path.dirname(file));
140
+ const exchanges = await parseConversation(file, project, file);
141
+ for (const exchange of exchanges) {
142
+ const toolNames = exchange.toolCalls?.map((tc) => tc.toolName);
143
+ const embedding = await generateExchangeEmbedding(exchange.userMessage, exchange.assistantMessage, toolNames);
144
+ insertExchange(db, exchange, embedding, toolNames);
145
+ }
146
+ result.indexed++;
147
+ }
148
+ catch (error) {
149
+ result.errors.push({
150
+ file,
151
+ error: error instanceof Error ? error.message : String(error),
152
+ });
153
+ }
154
+ }
155
+ db.close();
156
+ }
157
+ // Generate summaries for files that need them
158
+ if (!options.skipSummaries && filesToSummarize.length > 0) {
159
+ const { parseConversation } = await import("./parser.js");
160
+ const { summarizeConversation } = await import("./summarizer.js");
161
+ const summaryLimit = options.summaryLimit ?? 10;
162
+ const toSummarize = filesToSummarize.slice(0, summaryLimit);
163
+ const remaining = filesToSummarize.length - toSummarize.length;
164
+ console.log(`Generating summaries for ${toSummarize.length} conversation(s)...`);
165
+ if (remaining > 0) {
166
+ console.log(` (${remaining} more need summaries - will process on next sync)`);
167
+ }
168
+ for (const { path: filePath, sessionId } of toSummarize) {
169
+ try {
170
+ const project = path.basename(path.dirname(filePath));
171
+ const exchanges = await parseConversation(filePath, project, filePath);
172
+ if (exchanges.length === 0) {
173
+ // Skip empty conversations — write an empty -summary.txt sentinel so they aren't re-queued forever
174
+ const summaryPath = filePath.replace(".jsonl", "-summary.txt");
175
+ fs.writeFileSync(summaryPath, "", "utf-8");
176
+ continue;
177
+ }
178
+ console.log(` Summarizing ${path.basename(filePath)} (${exchanges.length} exchanges)...`);
179
+ const summary = await summarizeConversation(exchanges, sessionId);
180
+ const summaryPath = filePath.replace(".jsonl", "-summary.txt");
181
+ fs.writeFileSync(summaryPath, summary, "utf-8");
182
+ result.summarized++;
183
+ }
184
+ catch (error) {
185
+ // Write a structured error sentinel (#96): distinct from the empty
186
+ // zero-exchange sentinel so a stale failure can self-heal on the next
187
+ // sync run past the retry threshold. The marker also keeps the error
188
+ // text on disk for post-hoc diagnosis. Best-effort — if the sentinel
189
+ // write itself fails, fall through and surface the original error.
190
+ try {
191
+ const summaryPath = filePath.replace(".jsonl", "-summary.txt");
192
+ fs.writeFileSync(summaryPath, formatErrorSentinel(error), "utf-8");
193
+ }
194
+ catch { }
195
+ result.errors.push({
196
+ file: filePath,
197
+ error: `Summary generation failed: ${error instanceof Error ? error.message : String(error)}`,
198
+ });
199
+ }
200
+ }
201
+ }
202
+ return result;
203
+ }
204
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * The two record types.
3
+ *
4
+ * A **conversation exchange** is harvested: sync copies a transcript out of
5
+ * `~/.claude/projects` or `~/.codex/sessions` and the indexer derives rows from
6
+ * it. Nobody chose to write it down.
7
+ *
8
+ * A **journal entry** is deliberate: the model called `process_thoughts` and a
9
+ * markdown file was written. It is authored content with different privacy
10
+ * properties — a project entry belongs to the codebase, a user entry belongs to
11
+ * the person.
12
+ *
13
+ * They share one encoder and one SQLite file and nothing else. Distinct tables,
14
+ * distinct MCP tools, distinct result types. This file is where that boundary
15
+ * is stated.
16
+ *
17
+ * Reconciliation note: private-journal-mcp's own `types.ts` was entirely dead —
18
+ * `JournalEntry`, `ServerConfig` and `ProcessThoughtsRequest` had zero importers
19
+ * anywhere in its src or tests, while its live journal shape was retyped inline
20
+ * in four places. The names below are re-established as the single declaration
21
+ * those four sites now share.
22
+ */
23
+ export interface ToolCall {
24
+ id: string;
25
+ exchangeId: string;
26
+ toolName: string;
27
+ toolInput?: unknown;
28
+ toolResult?: string;
29
+ isError: boolean;
30
+ timestamp: string;
31
+ }
32
+ export type ConversationHarness = "claude" | "codex";
33
+ export interface ConversationExchange {
34
+ id: string;
35
+ project: string;
36
+ timestamp: string;
37
+ userMessage: string;
38
+ assistantMessage: string;
39
+ archivePath: string;
40
+ lineStart: number;
41
+ lineEnd: number;
42
+ parentUuid?: string | undefined;
43
+ isSidechain?: boolean | undefined;
44
+ harness?: ConversationHarness | undefined;
45
+ sessionId?: string | undefined;
46
+ cwd?: string | undefined;
47
+ gitBranch?: string | undefined;
48
+ claudeVersion?: string | undefined;
49
+ agentVersion?: string | undefined;
50
+ model?: string | undefined;
51
+ modelProvider?: string | undefined;
52
+ thinkingLevel?: string | undefined;
53
+ thinkingDisabled?: boolean | undefined;
54
+ thinkingTriggers?: string | undefined;
55
+ toolCalls?: ToolCall[] | undefined;
56
+ }
57
+ /** A conversation-search hit. */
58
+ export interface SearchResult {
59
+ exchange: ConversationExchange;
60
+ /** Cosine similarity, or undefined in `mode: 'text'` where there is no vector. */
61
+ similarity?: number | undefined;
62
+ snippet: string;
63
+ /** The conversation's AI summary sidecar, when one exists and is not an error sentinel. */
64
+ summary?: string | undefined;
65
+ }
66
+ export interface MultiConceptResult {
67
+ exchange: ConversationExchange;
68
+ snippet: string;
69
+ conceptSimilarities: number[];
70
+ averageSimilarity: number;
71
+ }
72
+ /**
73
+ * Which journal a record belongs to.
74
+ *
75
+ * Upstream this was derived at read time from which directory the file happened
76
+ * to be walked out of, and was not stored. It is a column now: derivation broke
77
+ * the moment both roots resolved to the same directory.
78
+ */
79
+ export type JournalScope = "project" | "user";
80
+ /**
81
+ * The six thought categories, in the order they are rendered into an entry.
82
+ *
83
+ * `project_notes` routes to the project journal; the other five route to the
84
+ * user journal. Snake_case because these are MCP wire names.
85
+ */
86
+ export interface JournalThoughts {
87
+ reflections?: string | undefined;
88
+ observations?: string | undefined;
89
+ project_notes?: string | undefined;
90
+ user_context?: string | undefined;
91
+ technical_insights?: string | undefined;
92
+ world_knowledge?: string | undefined;
93
+ }
94
+ /** The rendered `## Heading` for each thought category, in entry order. */
95
+ export declare const JOURNAL_SECTION_HEADINGS: ReadonlyArray<[keyof JournalThoughts, string]>;
96
+ /** One journal entry as it exists on disk and in the index. */
97
+ export interface JournalEntry {
98
+ /** Stable id: the entry's absolute path is not stable, the id is. */
99
+ id: string;
100
+ /** Absolute path of the markdown file, refreshed from the walk on every index. */
101
+ path: string;
102
+ /**
103
+ * Absolute path of the journal root this entry was found under.
104
+ *
105
+ * One database serves every project on the machine, so this is what makes a
106
+ * `project`-scoped entry belong to a repo: retrieval filters on it, and the
107
+ * index prune only considers rows whose root it is currently walking.
108
+ */
109
+ root: string;
110
+ scope: JournalScope;
111
+ /** Epoch milliseconds. */
112
+ timestamp: number;
113
+ /** Frontmatter-stripped, header-stripped body — what gets embedded. */
114
+ text: string;
115
+ /** Rendered section headings present in the entry, e.g. `['Reflections']`. */
116
+ sections: string[];
117
+ }
118
+ /** A journal-search hit. */
119
+ export interface JournalSearchResult {
120
+ entry: JournalEntry;
121
+ /** Cosine similarity in [-1, 1]. 1 for `list_recent_entries`, which does not rank. */
122
+ score: number;
123
+ excerpt: string;
124
+ }
125
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}