hippo-memory 0.36.0 → 0.37.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 (199) hide show
  1. package/README.md +16 -0
  2. package/dist/api.d.ts +20 -0
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/api.js +23 -3
  5. package/dist/api.js.map +1 -1
  6. package/dist/benchmarks/e1.3/incident-recall-eval.js +74 -0
  7. package/dist/benchmarks/e1.3/incident-recall-eval.js.map +1 -0
  8. package/dist/benchmarks/e1.3/scenarios.json +2587 -0
  9. package/dist/benchmarks/e1.3/slack-1000-event-smoke.js +102 -0
  10. package/dist/benchmarks/e1.3/slack-1000-event-smoke.js.map +1 -0
  11. package/dist/cli.js +82 -0
  12. package/dist/cli.js.map +1 -1
  13. package/dist/connectors/slack/backfill.d.ts +42 -0
  14. package/dist/connectors/slack/backfill.d.ts.map +1 -0
  15. package/dist/connectors/slack/backfill.js +76 -0
  16. package/dist/connectors/slack/backfill.js.map +1 -0
  17. package/dist/connectors/slack/deletion.d.ts +14 -0
  18. package/dist/connectors/slack/deletion.d.ts.map +1 -0
  19. package/dist/connectors/slack/deletion.js +46 -0
  20. package/dist/connectors/slack/deletion.js.map +1 -0
  21. package/dist/connectors/slack/dlq.d.ts +21 -0
  22. package/dist/connectors/slack/dlq.d.ts.map +1 -0
  23. package/dist/connectors/slack/dlq.js +23 -0
  24. package/dist/connectors/slack/dlq.js.map +1 -0
  25. package/dist/connectors/slack/idempotency.d.ts +5 -0
  26. package/dist/connectors/slack/idempotency.d.ts.map +1 -0
  27. package/dist/connectors/slack/idempotency.js +13 -0
  28. package/dist/connectors/slack/idempotency.js.map +1 -0
  29. package/dist/connectors/slack/ingest.d.ts +27 -0
  30. package/dist/connectors/slack/ingest.d.ts.map +1 -0
  31. package/dist/connectors/slack/ingest.js +48 -0
  32. package/dist/connectors/slack/ingest.js.map +1 -0
  33. package/dist/connectors/slack/ratelimit.d.ts +9 -0
  34. package/dist/connectors/slack/ratelimit.d.ts.map +1 -0
  35. package/dist/connectors/slack/ratelimit.js +18 -0
  36. package/dist/connectors/slack/ratelimit.js.map +1 -0
  37. package/dist/connectors/slack/scope.d.ts +16 -0
  38. package/dist/connectors/slack/scope.d.ts.map +1 -0
  39. package/dist/connectors/slack/scope.js +13 -0
  40. package/dist/connectors/slack/scope.js.map +1 -0
  41. package/dist/connectors/slack/signature.d.ts +12 -0
  42. package/dist/connectors/slack/signature.d.ts.map +1 -0
  43. package/dist/connectors/slack/signature.js +20 -0
  44. package/dist/connectors/slack/signature.js.map +1 -0
  45. package/dist/connectors/slack/tenant-routing.d.ts +13 -0
  46. package/dist/connectors/slack/tenant-routing.d.ts.map +1 -0
  47. package/dist/connectors/slack/tenant-routing.js +17 -0
  48. package/dist/connectors/slack/tenant-routing.js.map +1 -0
  49. package/dist/connectors/slack/transform.d.ts +20 -0
  50. package/dist/connectors/slack/transform.d.ts.map +1 -0
  51. package/dist/connectors/slack/transform.js +31 -0
  52. package/dist/connectors/slack/transform.js.map +1 -0
  53. package/dist/connectors/slack/types.d.ts +35 -0
  54. package/dist/connectors/slack/types.d.ts.map +1 -0
  55. package/dist/connectors/slack/types.js +23 -0
  56. package/dist/connectors/slack/types.js.map +1 -0
  57. package/dist/connectors/slack/web-client.d.ts +12 -0
  58. package/dist/connectors/slack/web-client.d.ts.map +1 -0
  59. package/dist/connectors/slack/web-client.js +43 -0
  60. package/dist/connectors/slack/web-client.js.map +1 -0
  61. package/dist/db.d.ts.map +1 -1
  62. package/dist/db.js +46 -1
  63. package/dist/db.js.map +1 -1
  64. package/dist/importers.js +3 -3
  65. package/dist/importers.js.map +1 -1
  66. package/dist/mcp/server.js +1 -1
  67. package/dist/server.d.ts.map +1 -1
  68. package/dist/server.js +174 -2
  69. package/dist/server.js.map +1 -1
  70. package/dist/src/ambient.js +147 -0
  71. package/dist/src/ambient.js.map +1 -0
  72. package/dist/src/api.js +343 -0
  73. package/dist/src/api.js.map +1 -0
  74. package/dist/src/audit.js +152 -0
  75. package/dist/src/audit.js.map +1 -0
  76. package/dist/src/auth.js +65 -0
  77. package/dist/src/auth.js.map +1 -0
  78. package/dist/src/autolearn.js +143 -0
  79. package/dist/src/autolearn.js.map +1 -0
  80. package/dist/src/capture.js +512 -0
  81. package/dist/src/capture.js.map +1 -0
  82. package/dist/src/cli.js +4971 -0
  83. package/dist/src/cli.js.map +1 -0
  84. package/dist/src/client.js +181 -0
  85. package/dist/src/client.js.map +1 -0
  86. package/dist/src/config.js +108 -0
  87. package/dist/src/config.js.map +1 -0
  88. package/dist/src/connectors/slack/backfill.js +76 -0
  89. package/dist/src/connectors/slack/backfill.js.map +1 -0
  90. package/dist/src/connectors/slack/deletion.js +46 -0
  91. package/dist/src/connectors/slack/deletion.js.map +1 -0
  92. package/dist/src/connectors/slack/dlq.js +23 -0
  93. package/dist/src/connectors/slack/dlq.js.map +1 -0
  94. package/dist/src/connectors/slack/idempotency.js +13 -0
  95. package/dist/src/connectors/slack/idempotency.js.map +1 -0
  96. package/dist/src/connectors/slack/ingest.js +48 -0
  97. package/dist/src/connectors/slack/ingest.js.map +1 -0
  98. package/dist/src/connectors/slack/ratelimit.js +18 -0
  99. package/dist/src/connectors/slack/ratelimit.js.map +1 -0
  100. package/dist/src/connectors/slack/scope.js +13 -0
  101. package/dist/src/connectors/slack/scope.js.map +1 -0
  102. package/dist/src/connectors/slack/signature.js +20 -0
  103. package/dist/src/connectors/slack/signature.js.map +1 -0
  104. package/dist/src/connectors/slack/tenant-routing.js +17 -0
  105. package/dist/src/connectors/slack/tenant-routing.js.map +1 -0
  106. package/dist/src/connectors/slack/transform.js +31 -0
  107. package/dist/src/connectors/slack/transform.js.map +1 -0
  108. package/dist/src/connectors/slack/types.js +23 -0
  109. package/dist/src/connectors/slack/types.js.map +1 -0
  110. package/dist/src/connectors/slack/web-client.js +43 -0
  111. package/dist/src/connectors/slack/web-client.js.map +1 -0
  112. package/dist/src/consolidate.js +517 -0
  113. package/dist/src/consolidate.js.map +1 -0
  114. package/dist/src/dag.js +104 -0
  115. package/dist/src/dag.js.map +1 -0
  116. package/dist/src/dashboard.js +409 -0
  117. package/dist/src/dashboard.js.map +1 -0
  118. package/dist/src/db.js +584 -0
  119. package/dist/src/db.js.map +1 -0
  120. package/dist/src/embeddings.js +344 -0
  121. package/dist/src/embeddings.js.map +1 -0
  122. package/dist/src/eval-suite.js +289 -0
  123. package/dist/src/eval-suite.js.map +1 -0
  124. package/dist/src/eval.js +187 -0
  125. package/dist/src/eval.js.map +1 -0
  126. package/dist/src/extract.js +87 -0
  127. package/dist/src/extract.js.map +1 -0
  128. package/dist/src/handoff.js +30 -0
  129. package/dist/src/handoff.js.map +1 -0
  130. package/dist/src/hooks.js +582 -0
  131. package/dist/src/hooks.js.map +1 -0
  132. package/dist/src/importers.js +399 -0
  133. package/dist/src/importers.js.map +1 -0
  134. package/dist/src/index.js +25 -0
  135. package/dist/src/index.js.map +1 -0
  136. package/dist/src/invalidation.js +94 -0
  137. package/dist/src/invalidation.js.map +1 -0
  138. package/dist/src/mcp/framing.js +45 -0
  139. package/dist/src/mcp/framing.js.map +1 -0
  140. package/dist/src/mcp/server.js +510 -0
  141. package/dist/src/mcp/server.js.map +1 -0
  142. package/dist/src/memory.js +280 -0
  143. package/dist/src/memory.js.map +1 -0
  144. package/dist/src/multihop.js +32 -0
  145. package/dist/src/multihop.js.map +1 -0
  146. package/dist/src/path-context.js +32 -0
  147. package/dist/src/path-context.js.map +1 -0
  148. package/dist/src/physics-config.js +26 -0
  149. package/dist/src/physics-config.js.map +1 -0
  150. package/dist/src/physics-state.js +163 -0
  151. package/dist/src/physics-state.js.map +1 -0
  152. package/dist/src/physics.js +361 -0
  153. package/dist/src/physics.js.map +1 -0
  154. package/dist/src/postinstall.js +68 -0
  155. package/dist/src/postinstall.js.map +1 -0
  156. package/dist/src/raw-archive.js +72 -0
  157. package/dist/src/raw-archive.js.map +1 -0
  158. package/dist/src/refine-llm.js +147 -0
  159. package/dist/src/refine-llm.js.map +1 -0
  160. package/dist/src/replay.js +117 -0
  161. package/dist/src/replay.js.map +1 -0
  162. package/dist/src/salience.js +74 -0
  163. package/dist/src/salience.js.map +1 -0
  164. package/dist/src/scheduler.js +67 -0
  165. package/dist/src/scheduler.js.map +1 -0
  166. package/dist/src/scope.js +35 -0
  167. package/dist/src/scope.js.map +1 -0
  168. package/dist/src/search.js +801 -0
  169. package/dist/src/search.js.map +1 -0
  170. package/dist/src/server-detect.js +70 -0
  171. package/dist/src/server-detect.js.map +1 -0
  172. package/dist/src/server.js +784 -0
  173. package/dist/src/server.js.map +1 -0
  174. package/dist/src/shared.js +309 -0
  175. package/dist/src/shared.js.map +1 -0
  176. package/dist/src/sso.js +22 -0
  177. package/dist/src/sso.js.map +1 -0
  178. package/dist/src/store.js +1390 -0
  179. package/dist/src/store.js.map +1 -0
  180. package/dist/src/tenant.js +17 -0
  181. package/dist/src/tenant.js.map +1 -0
  182. package/dist/src/trace.js +64 -0
  183. package/dist/src/trace.js.map +1 -0
  184. package/dist/src/working-memory.js +149 -0
  185. package/dist/src/working-memory.js.map +1 -0
  186. package/dist/src/yaml.js +98 -0
  187. package/dist/src/yaml.js.map +1 -0
  188. package/dist/store.d.ts +9 -1
  189. package/dist/store.d.ts.map +1 -1
  190. package/dist/store.js +30 -2
  191. package/dist/store.js.map +1 -1
  192. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  193. package/extensions/openclaw-plugin/package.json +1 -1
  194. package/openclaw.plugin.json +1 -1
  195. package/package.json +2 -2
  196. package/dist/import.d.ts +0 -31
  197. package/dist/import.d.ts.map +0 -1
  198. package/dist/import.js +0 -307
  199. package/dist/import.js.map +0 -1
@@ -0,0 +1,399 @@
1
+ /**
2
+ * Memory importers for Hippo.
3
+ * Imports memories from ChatGPT, Claude, Cursor, generic files, and structured markdown.
4
+ */
5
+ import * as fs from 'fs';
6
+ import { createMemory, Layer } from './memory.js';
7
+ import { loadAllEntries, writeEntry } from './store.js';
8
+ import { textOverlap } from './search.js';
9
+ import { getGlobalRoot, initGlobal } from './shared.js';
10
+ // ---------------------------------------------------------------------------
11
+ // Shared core: dedup + write
12
+ // ---------------------------------------------------------------------------
13
+ /**
14
+ * Given an array of raw text chunks, deduplicate against existing memories,
15
+ * create MemoryEntry objects, write them (unless dry-run), and return a result.
16
+ */
17
+ export function importEntries(chunks, source, tags, options) {
18
+ const targetRoot = options.global ? getGlobalRoot() : options.hippoRoot;
19
+ // Ensure store is ready
20
+ if (options.global) {
21
+ initGlobal();
22
+ }
23
+ const existing = loadAllEntries(targetRoot);
24
+ const allTags = [...new Set([...tags, ...(options.extraTags ?? [])])];
25
+ let total = 0;
26
+ let imported = 0;
27
+ let skipped = 0;
28
+ const entries = [];
29
+ for (const raw of chunks) {
30
+ const trimmed = raw.trim();
31
+ if (trimmed.length > 1000) {
32
+ console.error(`Warning: imported memory truncated from ${trimmed.length} to 1000 chars`);
33
+ }
34
+ const chunk = trimmed.slice(0, 1000);
35
+ // Skip empty or too-short chunks
36
+ if (!chunk || chunk.length < 10) {
37
+ skipped++;
38
+ continue;
39
+ }
40
+ total++;
41
+ // Dedup check: textOverlap > 0.7 with any existing memory = skip
42
+ let isDuplicate = false;
43
+ for (const existing_entry of existing) {
44
+ if (textOverlap(chunk, existing_entry.content) > 0.7) {
45
+ isDuplicate = true;
46
+ break;
47
+ }
48
+ }
49
+ if (isDuplicate) {
50
+ skipped++;
51
+ continue;
52
+ }
53
+ // A3: kind defaults to 'distilled'. ChatGPT/Claude/Cursor exports are curated
54
+ // user pastes, not raw transcripts from a system of record, so distilled is
55
+ // correct here. E1.3 (Slack ingestion) shipped 2026-04-29 in src/connectors/slack/
56
+ // and sets kind: 'raw' + routes deletions through archiveRawMemory() — these
57
+ // importers stay 'distilled' per the original reasoning. See MEMORY_ENVELOPE.md.
58
+ const entry = createMemory(chunk, {
59
+ layer: Layer.Episodic,
60
+ tags: allTags,
61
+ source,
62
+ confidence: 'observed',
63
+ });
64
+ entries.push(entry);
65
+ if (!options.dryRun) {
66
+ writeEntry(targetRoot, entry);
67
+ // Add to existing so subsequent chunks dedup against freshly imported ones
68
+ existing.push(entry);
69
+ }
70
+ imported++;
71
+ }
72
+ return { total, imported, skipped, entries };
73
+ }
74
+ // ---------------------------------------------------------------------------
75
+ // ChatGPT importer
76
+ // ---------------------------------------------------------------------------
77
+ /**
78
+ * Parse ChatGPT memory export file.
79
+ * Supports:
80
+ * - JSON array of strings: ["memory 1", "memory 2"]
81
+ * - JSON array of objects: [{"content": "...", "created": "..."}]
82
+ * - ChatGPT export format: {"memories": [{"content": "...", "created_at": "..."}]}
83
+ * - Plain text: one memory per line
84
+ */
85
+ function parseChatGPTFile(filePath) {
86
+ const raw = fs.readFileSync(filePath, 'utf8').trim();
87
+ // Try JSON first
88
+ if (raw.startsWith('[') || raw.startsWith('{')) {
89
+ try {
90
+ const parsed = JSON.parse(raw);
91
+ // {"memories": [...]} - ChatGPT export format
92
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed) && Array.isArray(parsed.memories)) {
93
+ return parsed.memories
94
+ .map((m) => {
95
+ if (typeof m === 'string')
96
+ return m;
97
+ if (m && typeof m === 'object') {
98
+ const obj = m;
99
+ return String(obj['content'] ?? obj['text'] ?? '');
100
+ }
101
+ return '';
102
+ })
103
+ .filter(Boolean);
104
+ }
105
+ // Array format
106
+ if (Array.isArray(parsed)) {
107
+ return parsed
108
+ .map((m) => {
109
+ if (typeof m === 'string')
110
+ return m;
111
+ if (m && typeof m === 'object') {
112
+ const obj = m;
113
+ return String(obj['content'] ?? obj['text'] ?? '');
114
+ }
115
+ return '';
116
+ })
117
+ .filter(Boolean);
118
+ }
119
+ }
120
+ catch {
121
+ // Fall through to plain text
122
+ }
123
+ }
124
+ // Plain text: one memory per line
125
+ return raw.split('\n').map((l) => l.trim()).filter(Boolean);
126
+ }
127
+ export function importChatGPT(filePath, options) {
128
+ const chunks = parseChatGPTFile(filePath);
129
+ return importEntries(chunks, 'import:chatgpt', ['imported', 'chatgpt'], options);
130
+ }
131
+ // ---------------------------------------------------------------------------
132
+ // Claude importer
133
+ // ---------------------------------------------------------------------------
134
+ const HIPPO_START = '<!-- hippo:start -->';
135
+ const HIPPO_END = '<!-- hippo:end -->';
136
+ /**
137
+ * Strip the hippo hook block from markdown content.
138
+ */
139
+ function stripHippoBlock(content) {
140
+ const startIdx = content.indexOf(HIPPO_START);
141
+ const endIdx = content.indexOf(HIPPO_END);
142
+ if (startIdx === -1 || endIdx === -1)
143
+ return content;
144
+ return content.slice(0, startIdx) + content.slice(endIdx + HIPPO_END.length);
145
+ }
146
+ /**
147
+ * Split markdown into meaningful chunks (headings + bullet points).
148
+ */
149
+ function splitMarkdown(content) {
150
+ const chunks = [];
151
+ const lines = content.split('\n');
152
+ let current = '';
153
+ for (const line of lines) {
154
+ const trimmed = line.trim();
155
+ // Heading: start a new chunk
156
+ if (/^#{1,6}\s+/.test(trimmed)) {
157
+ if (current.trim())
158
+ chunks.push(current.trim());
159
+ current = trimmed;
160
+ continue;
161
+ }
162
+ // Bullet point: each bullet is its own chunk (flush previous if not a bullet context)
163
+ if (/^[-*+]\s+/.test(trimmed)) {
164
+ if (current.trim() && !/^[-*+]\s+/.test(current.split('\n')[0])) {
165
+ chunks.push(current.trim());
166
+ current = '';
167
+ }
168
+ if (current.trim()) {
169
+ chunks.push(current.trim());
170
+ current = '';
171
+ }
172
+ current = trimmed.replace(/^[-*+]\s+/, '').trim();
173
+ continue;
174
+ }
175
+ // Numbered list item
176
+ if (/^\d+\.\s+/.test(trimmed)) {
177
+ if (current.trim()) {
178
+ chunks.push(current.trim());
179
+ current = '';
180
+ }
181
+ current = trimmed.replace(/^\d+\.\s+/, '').trim();
182
+ continue;
183
+ }
184
+ // Empty line
185
+ if (!trimmed) {
186
+ if (current.trim()) {
187
+ chunks.push(current.trim());
188
+ current = '';
189
+ }
190
+ continue;
191
+ }
192
+ // Regular line: append to current
193
+ current = current ? current + ' ' + trimmed : trimmed;
194
+ }
195
+ if (current.trim())
196
+ chunks.push(current.trim());
197
+ return chunks.filter(Boolean);
198
+ }
199
+ /**
200
+ * Parse CLAUDE.md or Claude memory.json.
201
+ */
202
+ function parseClaudeFile(filePath) {
203
+ const raw = fs.readFileSync(filePath, 'utf8');
204
+ // JSON memory file
205
+ if (filePath.endsWith('.json')) {
206
+ try {
207
+ const parsed = JSON.parse(raw.trim());
208
+ if (Array.isArray(parsed)) {
209
+ return parsed
210
+ .map((m) => {
211
+ if (typeof m === 'string')
212
+ return m;
213
+ if (m && typeof m === 'object') {
214
+ const obj = m;
215
+ return String(obj['content'] ?? obj['text'] ?? '');
216
+ }
217
+ return '';
218
+ })
219
+ .filter(Boolean);
220
+ }
221
+ }
222
+ catch {
223
+ // Fall through to markdown
224
+ }
225
+ }
226
+ // Markdown file: strip hippo block and split
227
+ const cleaned = stripHippoBlock(raw);
228
+ return splitMarkdown(cleaned);
229
+ }
230
+ export function importClaude(filePath, options) {
231
+ const chunks = parseClaudeFile(filePath);
232
+ return importEntries(chunks, 'import:claude', ['imported', 'claude'], options);
233
+ }
234
+ // ---------------------------------------------------------------------------
235
+ // Cursor importer
236
+ // ---------------------------------------------------------------------------
237
+ /**
238
+ * Split cursor rules file into chunks.
239
+ * Priority: numbered items, then bullet points, then double newlines.
240
+ */
241
+ function parseCursorFile(content) {
242
+ const chunks = [];
243
+ const lines = content.split('\n');
244
+ let current = '';
245
+ for (const line of lines) {
246
+ const trimmed = line.trim();
247
+ // Skip comment-only lines that are empty after stripping #
248
+ if (!trimmed || trimmed === '#') {
249
+ if (current.trim()) {
250
+ chunks.push(current.trim());
251
+ current = '';
252
+ }
253
+ continue;
254
+ }
255
+ // Numbered item: 1. 2. 3.
256
+ if (/^\d+\.\s+/.test(trimmed)) {
257
+ if (current.trim()) {
258
+ chunks.push(current.trim());
259
+ current = '';
260
+ }
261
+ current = trimmed.replace(/^\d+\.\s+/, '').trim();
262
+ continue;
263
+ }
264
+ // Bullet: - or *
265
+ if (/^[-*]\s+/.test(trimmed)) {
266
+ if (current.trim()) {
267
+ chunks.push(current.trim());
268
+ current = '';
269
+ }
270
+ current = trimmed.replace(/^[-*]\s+/, '').trim();
271
+ continue;
272
+ }
273
+ // Regular line
274
+ current = current ? current + ' ' + trimmed : trimmed;
275
+ }
276
+ if (current.trim())
277
+ chunks.push(current.trim());
278
+ // Also split on double newlines within chunks if they somehow ended up there
279
+ return chunks.flatMap((c) => {
280
+ const parts = c.split(/\n{2,}/);
281
+ return parts.map((p) => p.trim()).filter(Boolean);
282
+ });
283
+ }
284
+ export function importCursor(filePath, options) {
285
+ const raw = fs.readFileSync(filePath, 'utf8');
286
+ const chunks = parseCursorFile(raw);
287
+ return importEntries(chunks, 'import:cursor', ['imported', 'cursor'], options);
288
+ }
289
+ // ---------------------------------------------------------------------------
290
+ // Generic file importer
291
+ // ---------------------------------------------------------------------------
292
+ /**
293
+ * Split a generic file into chunks.
294
+ * Markdown: split on headings and bullet points.
295
+ * Plain text: split on double newlines or one-per-line.
296
+ */
297
+ function parseGenericFile(filePath) {
298
+ const raw = fs.readFileSync(filePath, 'utf8');
299
+ const isMarkdown = filePath.endsWith('.md') || filePath.endsWith('.mdx');
300
+ if (isMarkdown) {
301
+ return splitMarkdown(raw);
302
+ }
303
+ // Plain text: try double newlines first
304
+ const byParagraph = raw.split(/\n{2,}/).map((p) => p.trim()).filter(Boolean);
305
+ if (byParagraph.length > 1)
306
+ return byParagraph;
307
+ // Fall back to one-per-line
308
+ return raw.split('\n').map((l) => l.trim()).filter(Boolean);
309
+ }
310
+ export function importGenericFile(filePath, options) {
311
+ const chunks = parseGenericFile(filePath);
312
+ return importEntries(chunks, 'import:file', ['imported'], options);
313
+ }
314
+ // ---------------------------------------------------------------------------
315
+ // Structured markdown importer (MEMORY.md / AGENTS.md format)
316
+ // ---------------------------------------------------------------------------
317
+ /**
318
+ * Slugify a heading for use as a tag.
319
+ * "Data Pipeline & Cache" -> "data-pipeline-cache"
320
+ */
321
+ function slugify(heading) {
322
+ return heading
323
+ .toLowerCase()
324
+ .replace(/[^a-z0-9\s-]/g, ' ')
325
+ .trim()
326
+ .replace(/\s+/g, '-')
327
+ .replace(/-+/g, '-')
328
+ .slice(0, 50);
329
+ }
330
+ /**
331
+ * Parse structured markdown into {content, sectionSlug} pairs.
332
+ * Each heading starts a new section. Bullet points / numbered items under
333
+ * the heading become individual memories tagged with the section slug.
334
+ */
335
+ function parseStructuredMarkdown(raw) {
336
+ const results = [];
337
+ const lines = raw.split('\n');
338
+ let currentSection = '';
339
+ let currentSlug = '';
340
+ let pendingText = '';
341
+ function flush() {
342
+ if (!pendingText.trim())
343
+ return;
344
+ results.push({ content: pendingText.trim(), sectionSlug: currentSlug });
345
+ pendingText = '';
346
+ }
347
+ for (const line of lines) {
348
+ const trimmed = line.trim();
349
+ // Heading
350
+ const headingMatch = trimmed.match(/^(#{1,6})\s+(.+)/);
351
+ if (headingMatch) {
352
+ flush();
353
+ currentSection = headingMatch[2].trim();
354
+ currentSlug = slugify(currentSection);
355
+ continue;
356
+ }
357
+ // Bullet or numbered item: flush previous, start new
358
+ if (/^[-*+]\s+/.test(trimmed) || /^\d+\.\s+/.test(trimmed)) {
359
+ flush();
360
+ const itemText = trimmed.replace(/^[-*+]\s+/, '').replace(/^\d+\.\s+/, '').trim();
361
+ pendingText = itemText;
362
+ continue;
363
+ }
364
+ // Empty line: flush current pending
365
+ if (!trimmed) {
366
+ flush();
367
+ continue;
368
+ }
369
+ // Continuation of current item
370
+ pendingText = pendingText ? pendingText + ' ' + trimmed : trimmed;
371
+ }
372
+ flush();
373
+ return results.filter((r) => r.content.length > 0);
374
+ }
375
+ export function importMarkdown(filePath, options) {
376
+ const raw = fs.readFileSync(filePath, 'utf8');
377
+ const parsed = parseStructuredMarkdown(raw);
378
+ // Group by section slug so we can pass per-chunk tags
379
+ // We call importEntries per unique slug to get the right tags per section
380
+ const bySlug = new Map();
381
+ for (const { content, sectionSlug } of parsed) {
382
+ const list = bySlug.get(sectionSlug) ?? [];
383
+ list.push(content);
384
+ bySlug.set(sectionSlug, list);
385
+ }
386
+ let totalResult = { total: 0, imported: 0, skipped: 0, entries: [] };
387
+ for (const [slug, chunks] of bySlug.entries()) {
388
+ const sectionTags = slug ? ['imported', slug] : ['imported'];
389
+ const result = importEntries(chunks, 'import:markdown', sectionTags, options);
390
+ totalResult = {
391
+ total: totalResult.total + result.total,
392
+ imported: totalResult.imported + result.imported,
393
+ skipped: totalResult.skipped + result.skipped,
394
+ entries: [...totalResult.entries, ...result.entries],
395
+ };
396
+ }
397
+ return totalResult;
398
+ }
399
+ //# sourceMappingURL=importers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"importers.js","sourceRoot":"","sources":["../../src/importers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Hippo public API - re-exports for programmatic use.
3
+ */
4
+ export { Layer, calculateStrength, resolveConfidence, createMemory, applyOutcome, generateId, computeSchemaFit } from './memory.js';
5
+ export { search, hybridSearch, physicsSearch, markRetrieved, estimateTokens, textOverlap, tokenize, explainMatch, detectTemporalDirection, temporalBoost, computeTemporalRange } from './search.js';
6
+ export { multihopSearch } from './multihop.js';
7
+ export { initStore, loadAllEntries, loadSearchEntries, writeEntry, readEntry, deleteEntry, loadIndex, rebuildIndex, saveActiveTaskSnapshot, loadActiveTaskSnapshot, clearActiveTaskSnapshot, appendSessionEvent, listSessionEvents, listMemoryConflicts, replaceDetectedConflicts, resolveConflict, saveSessionHandoff, loadLatestHandoff, loadHandoffById, loadSessionDecayContext, } from './store.js';
8
+ export { consolidate } from './consolidate.js';
9
+ // Feature 1: Embedding search
10
+ export { isEmbeddingAvailable, getEmbedding, cosineSimilarity, loadEmbeddingIndex, saveEmbeddingIndex, embedMemory, embedAll, } from './embeddings.js';
11
+ // Feature 2: Auto-learn from errors
12
+ export { captureError, extractLessons, deduplicateLesson, runWatched, fetchGitLog, } from './autolearn.js';
13
+ // Feature 3: Cross-agent shared memory
14
+ export { getGlobalRoot, initGlobal, promoteToGlobal, searchBoth, searchBothHybrid, syncGlobalToLocal, transferScore, shareMemory, listPeers, autoShare, } from './shared.js';
15
+ // Feature 5: Working memory
16
+ export { wmPush, wmRead, wmClear, wmFlush, WM_MAX_ENTRIES, } from './working-memory.js';
17
+ // Feature 4: Memory importers
18
+ export { importChatGPT, importClaude, importCursor, importGenericFile, importMarkdown, importEntries, } from './importers.js';
19
+ // Feature eval suite
20
+ export { runFeatureEval, formatResult, resultToBaseline, detectRegressions, buildSyntheticCorpus, } from './eval-suite.js';
21
+ // Pineal gland: salience gate
22
+ export { computeSalience, } from './salience.js';
23
+ // Pineal gland: ambient state vector
24
+ export { computeAmbientState, renderAmbientSummary, formatAmbientVector, } from './ambient.js';
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAe,KAAK,EAAmD,iBAAiB,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAClM,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,uBAAuB,EAAE,aAAa,EAAE,oBAAoB,EAAkC,MAAM,aAAa,CAAC;AACpO,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,WAAW,EACX,SAAS,EACT,YAAY,EACZ,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,wBAAwB,EACxB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,uBAAuB,GAExB,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAE,WAAW,EAAuB,MAAM,kBAAkB,CAAC;AAEpE,8BAA8B;AAC9B,OAAO,EACL,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,oCAAoC;AACpC,OAAO,EACL,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,WAAW,GACZ,MAAM,gBAAgB,CAAC;AAExB,uCAAuC;AACvC,OAAO,EACL,aAAa,EACb,UAAU,EACV,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EAEjB,aAAa,EACb,WAAW,EACX,SAAS,EACT,SAAS,GACV,MAAM,aAAa,CAAC;AAErB,4BAA4B;AAC5B,OAAO,EACL,MAAM,EACN,MAAM,EACN,OAAO,EACP,OAAO,EAEP,cAAc,GACf,MAAM,qBAAqB,CAAC;AAE7B,8BAA8B;AAC9B,OAAO,EACL,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,aAAa,GAGd,MAAM,gBAAgB,CAAC;AAExB,qBAAqB;AACrB,OAAO,EACL,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAEzB,8BAA8B;AAC9B,OAAO,EACL,eAAe,GAIhB,MAAM,eAAe,CAAC;AAEvB,qCAAqC;AACrC,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,GAEpB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,94 @@
1
+ import { loadAllEntries, writeEntry } from './store.js';
2
+ /**
3
+ * Extract what was replaced/removed from a commit message.
4
+ * Returns null if the commit isn't a breaking/migration change.
5
+ */
6
+ export function extractInvalidationTarget(message) {
7
+ // Strip conventional commit prefix (e.g., "feat(scope): ")
8
+ const body = message.replace(/^[a-z]+(\([^)]*\))?:\s*/i, '').trim();
9
+ // Pattern: "migrate/switch/move/convert/transition/upgrade from X to Y"
10
+ const fromToMatch = body.match(/(?:migrat\w+|switch\w*|mov\w+|convert\w*|transition\w*|upgrad\w+)\s+(?:from\s+)?(.+?)\s+to\s+(.+)/i);
11
+ if (fromToMatch) {
12
+ return { from: fromToMatch[1].trim(), to: fromToMatch[2].trim(), type: 'migration' };
13
+ }
14
+ // Pattern: "from X to Y" (standalone)
15
+ const standaloneFromTo = body.match(/from\s+(.+?)\s+to\s+(.+)/i);
16
+ if (standaloneFromTo) {
17
+ return { from: standaloneFromTo[1].trim(), to: standaloneFromTo[2].trim(), type: 'migration' };
18
+ }
19
+ // Pattern: "replace X with Y"
20
+ const replaceMatch = body.match(/replac\w+\s+(.+?)\s+with\s+(.+)/i);
21
+ if (replaceMatch) {
22
+ return { from: replaceMatch[1].trim(), to: replaceMatch[2].trim(), type: 'migration' };
23
+ }
24
+ // Pattern: "deprecate X"
25
+ const deprecateMatch = body.match(/deprecat\w+\s+(.+)/i);
26
+ if (deprecateMatch) {
27
+ return { from: deprecateMatch[1].trim(), to: null, type: 'deprecation' };
28
+ }
29
+ // Pattern: "remove/drop X" (but not trivial removals)
30
+ const removeMatch = body.match(/(?:remov\w+|drop\w*)\s+(.+)/i);
31
+ if (removeMatch) {
32
+ const target = removeMatch[1].trim();
33
+ const words = target.split(/\s+/);
34
+ const trivialWords = new Set(['extra', 'unused', 'empty', 'old', 'whitespace', 'spaces', 'blank', 'dead', 'commented']);
35
+ const isTrivial = words.length <= 2 && words.some(w => trivialWords.has(w.toLowerCase()));
36
+ if (isTrivial)
37
+ return null;
38
+ return { from: target, to: null, type: 'removal' };
39
+ }
40
+ return null;
41
+ }
42
+ /**
43
+ * Find memories that reference the invalidated pattern and weaken them.
44
+ * - Halves half_life_days
45
+ * - Sets confidence to 'stale'
46
+ * - Adds 'invalidated' tag
47
+ * - Skips pinned memories
48
+ */
49
+ export function invalidateMatching(hippoRoot, target) {
50
+ const entries = loadAllEntries(hippoRoot);
51
+ const fromTokens = invalidationTokenize(target.from);
52
+ const result = { invalidated: 0, targets: [] };
53
+ for (const entry of entries) {
54
+ if (entry.pinned)
55
+ continue;
56
+ const contentTokens = invalidationTokenize(entry.content);
57
+ const tagTokens = entry.tags.map(t => t.toLowerCase());
58
+ // Check if the memory references the old pattern
59
+ const tokenMatch = matchScore(fromTokens, contentTokens);
60
+ const tagMatch = fromTokens.some(t => tagTokens.includes(t));
61
+ if (tokenMatch >= 0.5 || tagMatch) {
62
+ entry.half_life_days = Math.max(1, Math.floor(entry.half_life_days / 2));
63
+ entry.confidence = 'stale';
64
+ if (!entry.tags.includes('invalidated')) {
65
+ entry.tags.push('invalidated');
66
+ }
67
+ writeEntry(hippoRoot, entry);
68
+ result.invalidated++;
69
+ result.targets.push(entry.id);
70
+ }
71
+ }
72
+ return result;
73
+ }
74
+ const STOPWORDS = new Set([
75
+ 'the', 'an', 'is', 'it', 'in', 'on', 'at', 'to', 'for', 'of', 'by',
76
+ 'and', 'or', 'but', 'not', 'with', 'from', 'that', 'this', 'was', 'are',
77
+ 'be', 'has', 'had', 'have', 'been', 'will', 'would', 'could', 'should',
78
+ 'do', 'does', 'did', 'all', 'our', 'old', 'new', 'use', 'used', 'using',
79
+ ]);
80
+ function invalidationTokenize(text) {
81
+ return text
82
+ .toLowerCase()
83
+ .replace(/[^a-z0-9\s_.-]/g, ' ')
84
+ .split(/\s+/)
85
+ .filter(t => t.length >= 2 && !STOPWORDS.has(t));
86
+ }
87
+ function matchScore(fromTokens, contentTokens) {
88
+ if (fromTokens.length === 0)
89
+ return 0;
90
+ const contentSet = new Set(contentTokens);
91
+ const matches = fromTokens.filter(t => contentSet.has(t)).length;
92
+ return matches / fromTokens.length;
93
+ }
94
+ //# sourceMappingURL=invalidation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invalidation.js","sourceRoot":"","sources":["../../src/invalidation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ // MCP stdio transport framing.
2
+ //
3
+ // Spec: messages are newline-delimited JSON-RPC, with no embedded newlines.
4
+ // https://modelcontextprotocol.io/specification/.../basic/transports#stdio
5
+ // We also accept legacy LSP-style `Content-Length` framing so the
6
+ // printf-and-pipe smoke test from issue #13 still works.
7
+ const HEADER_DELIM = Buffer.from('\r\n\r\n');
8
+ export function parseFrame(buffer) {
9
+ // Strip leading whitespace/newlines between messages.
10
+ let start = 0;
11
+ while (start < buffer.length &&
12
+ (buffer[start] === 0x0a || buffer[start] === 0x0d ||
13
+ buffer[start] === 0x20 || buffer[start] === 0x09)) {
14
+ start++;
15
+ }
16
+ if (start === buffer.length)
17
+ return { kind: 'incomplete' };
18
+ const trimmed = buffer.subarray(start);
19
+ // LSP-style Content-Length framing.
20
+ if (trimmed[0] === 0x43 /* 'C' */ || trimmed[0] === 0x63 /* 'c' */) {
21
+ const headerEnd = trimmed.indexOf(HEADER_DELIM);
22
+ if (headerEnd === -1)
23
+ return { kind: 'incomplete' };
24
+ const header = trimmed.subarray(0, headerEnd).toString('utf-8');
25
+ const match = header.match(/Content-Length:\s*(\d+)/i);
26
+ if (!match)
27
+ return { kind: 'skip', rest: Buffer.from(trimmed.subarray(headerEnd + 4)) };
28
+ const contentLength = parseInt(match[1], 10);
29
+ const bodyStart = headerEnd + 4;
30
+ if (trimmed.length < bodyStart + contentLength)
31
+ return { kind: 'incomplete' };
32
+ const body = trimmed.subarray(bodyStart, bodyStart + contentLength).toString('utf-8');
33
+ return { kind: 'message', body, rest: Buffer.from(trimmed.subarray(bodyStart + contentLength)) };
34
+ }
35
+ // Newline-delimited JSON (MCP spec).
36
+ const newlineIdx = trimmed.indexOf(0x0a);
37
+ if (newlineIdx === -1)
38
+ return { kind: 'incomplete' };
39
+ const line = trimmed.subarray(0, newlineIdx).toString('utf-8').trimEnd();
40
+ const rest = Buffer.from(trimmed.subarray(newlineIdx + 1));
41
+ if (!line)
42
+ return { kind: 'skip', rest };
43
+ return { kind: 'message', body: line, rest };
44
+ }
45
+ //# sourceMappingURL=framing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framing.js","sourceRoot":"","sources":["../../../src/mcp/framing.ts"],"names":[],"mappings":"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"}