@psiclawops/hypermem 0.1.0 → 0.5.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 (93) hide show
  1. package/ARCHITECTURE.md +4 -3
  2. package/README.md +457 -174
  3. package/package.json +15 -5
  4. package/dist/background-indexer.d.ts +0 -117
  5. package/dist/background-indexer.d.ts.map +0 -1
  6. package/dist/background-indexer.js +0 -732
  7. package/dist/compaction-fence.d.ts +0 -89
  8. package/dist/compaction-fence.d.ts.map +0 -1
  9. package/dist/compaction-fence.js +0 -153
  10. package/dist/compositor.d.ts +0 -139
  11. package/dist/compositor.d.ts.map +0 -1
  12. package/dist/compositor.js +0 -1109
  13. package/dist/cross-agent.d.ts +0 -57
  14. package/dist/cross-agent.d.ts.map +0 -1
  15. package/dist/cross-agent.js +0 -254
  16. package/dist/db.d.ts +0 -131
  17. package/dist/db.d.ts.map +0 -1
  18. package/dist/db.js +0 -398
  19. package/dist/desired-state-store.d.ts +0 -100
  20. package/dist/desired-state-store.d.ts.map +0 -1
  21. package/dist/desired-state-store.js +0 -212
  22. package/dist/doc-chunk-store.d.ts +0 -115
  23. package/dist/doc-chunk-store.d.ts.map +0 -1
  24. package/dist/doc-chunk-store.js +0 -278
  25. package/dist/doc-chunker.d.ts +0 -99
  26. package/dist/doc-chunker.d.ts.map +0 -1
  27. package/dist/doc-chunker.js +0 -324
  28. package/dist/episode-store.d.ts +0 -48
  29. package/dist/episode-store.d.ts.map +0 -1
  30. package/dist/episode-store.js +0 -135
  31. package/dist/fact-store.d.ts +0 -57
  32. package/dist/fact-store.d.ts.map +0 -1
  33. package/dist/fact-store.js +0 -175
  34. package/dist/fleet-store.d.ts +0 -144
  35. package/dist/fleet-store.d.ts.map +0 -1
  36. package/dist/fleet-store.js +0 -276
  37. package/dist/hybrid-retrieval.d.ts +0 -60
  38. package/dist/hybrid-retrieval.d.ts.map +0 -1
  39. package/dist/hybrid-retrieval.js +0 -340
  40. package/dist/index.d.ts +0 -611
  41. package/dist/index.d.ts.map +0 -1
  42. package/dist/index.js +0 -1042
  43. package/dist/knowledge-graph.d.ts +0 -110
  44. package/dist/knowledge-graph.d.ts.map +0 -1
  45. package/dist/knowledge-graph.js +0 -305
  46. package/dist/knowledge-store.d.ts +0 -72
  47. package/dist/knowledge-store.d.ts.map +0 -1
  48. package/dist/knowledge-store.js +0 -241
  49. package/dist/library-schema.d.ts +0 -22
  50. package/dist/library-schema.d.ts.map +0 -1
  51. package/dist/library-schema.js +0 -717
  52. package/dist/message-store.d.ts +0 -76
  53. package/dist/message-store.d.ts.map +0 -1
  54. package/dist/message-store.js +0 -273
  55. package/dist/preference-store.d.ts +0 -54
  56. package/dist/preference-store.d.ts.map +0 -1
  57. package/dist/preference-store.js +0 -109
  58. package/dist/preservation-gate.d.ts +0 -82
  59. package/dist/preservation-gate.d.ts.map +0 -1
  60. package/dist/preservation-gate.js +0 -150
  61. package/dist/provider-translator.d.ts +0 -40
  62. package/dist/provider-translator.d.ts.map +0 -1
  63. package/dist/provider-translator.js +0 -349
  64. package/dist/rate-limiter.d.ts +0 -76
  65. package/dist/rate-limiter.d.ts.map +0 -1
  66. package/dist/rate-limiter.js +0 -179
  67. package/dist/redis.d.ts +0 -188
  68. package/dist/redis.d.ts.map +0 -1
  69. package/dist/redis.js +0 -534
  70. package/dist/schema.d.ts +0 -15
  71. package/dist/schema.d.ts.map +0 -1
  72. package/dist/schema.js +0 -203
  73. package/dist/secret-scanner.d.ts +0 -51
  74. package/dist/secret-scanner.d.ts.map +0 -1
  75. package/dist/secret-scanner.js +0 -248
  76. package/dist/seed.d.ts +0 -108
  77. package/dist/seed.d.ts.map +0 -1
  78. package/dist/seed.js +0 -177
  79. package/dist/system-store.d.ts +0 -73
  80. package/dist/system-store.d.ts.map +0 -1
  81. package/dist/system-store.js +0 -182
  82. package/dist/topic-store.d.ts +0 -45
  83. package/dist/topic-store.d.ts.map +0 -1
  84. package/dist/topic-store.js +0 -136
  85. package/dist/types.d.ts +0 -329
  86. package/dist/types.d.ts.map +0 -1
  87. package/dist/types.js +0 -9
  88. package/dist/vector-store.d.ts +0 -132
  89. package/dist/vector-store.d.ts.map +0 -1
  90. package/dist/vector-store.js +0 -498
  91. package/dist/work-store.d.ts +0 -112
  92. package/dist/work-store.d.ts.map +0 -1
  93. package/dist/work-store.js +0 -273
@@ -1,241 +0,0 @@
1
- /**
2
- * HyperMem Knowledge Store
3
- *
4
- * Long-term structured knowledge — replaces MEMORY.md.
5
- * Lives in the central library DB.
6
- * Knowledge entries are keyed (domain + key), versioned via superseded_by,
7
- * and linked to each other via knowledge_links.
8
- */
9
- function nowIso() {
10
- return new Date().toISOString();
11
- }
12
- function parseKnowledgeRow(row) {
13
- return {
14
- id: row.id,
15
- agentId: row.agent_id,
16
- domain: row.domain,
17
- key: row.key,
18
- content: row.content,
19
- confidence: row.confidence,
20
- sourceType: row.source_type,
21
- sourceRef: row.source_ref || null,
22
- createdAt: row.created_at,
23
- updatedAt: row.updated_at,
24
- expiresAt: row.expires_at || null,
25
- supersededBy: row.superseded_by || null,
26
- };
27
- }
28
- export class KnowledgeStore {
29
- db;
30
- constructor(db) {
31
- this.db = db;
32
- }
33
- /**
34
- * Upsert a knowledge entry.
35
- *
36
- * Versioning semantics:
37
- * - If no active entry exists: insert as version 1
38
- * - If same content: refresh confidence + timestamp only (no new version)
39
- * - If different content: insert as new version (max_version + 1), mark
40
- * previous active row as superseded_by = new_id
41
- *
42
- * This guarantees version history is real rows, not in-place overwrites.
43
- * The unique constraint is (agent_id, domain, key, version) so each
44
- * version is a distinct row.
45
- */
46
- upsert(agentId, domain, key, content, opts) {
47
- const now = nowIso();
48
- const sourceType = opts?.sourceType || 'manual';
49
- const confidence = opts?.confidence ?? 1.0;
50
- const visibility = opts?.visibility ?? 'private';
51
- // Find current active entry (not superseded, not expired)
52
- const existing = this.db.prepare(`
53
- SELECT * FROM knowledge
54
- WHERE agent_id = ? AND domain = ? AND key = ?
55
- AND superseded_by IS NULL
56
- AND (expires_at IS NULL OR expires_at > datetime('now'))
57
- ORDER BY version DESC LIMIT 1
58
- `).get(agentId, domain, key);
59
- if (existing && existing.content === content) {
60
- // Same content — refresh confidence and timestamp only, no new version
61
- this.db.prepare('UPDATE knowledge SET confidence = ?, updated_at = ? WHERE id = ?').run(confidence, now, existing.id);
62
- return parseKnowledgeRow({ ...existing, confidence, updated_at: now });
63
- }
64
- // Determine next version number
65
- const maxVersionRow = this.db.prepare(`
66
- SELECT MAX(version) AS max_version FROM knowledge
67
- WHERE agent_id = ? AND domain = ? AND key = ?
68
- `).get(agentId, domain, key);
69
- const nextVersion = (maxVersionRow?.max_version ?? 0) + 1;
70
- // Insert new version row (no ON CONFLICT — version column ensures uniqueness)
71
- const result = this.db.prepare(`
72
- INSERT INTO knowledge
73
- (agent_id, domain, key, version, content, confidence, visibility, source_type, source_ref,
74
- created_at, updated_at, expires_at)
75
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
76
- `).run(agentId, domain, key, nextVersion, content, confidence, visibility, sourceType, opts?.sourceRef ?? null, now, now, opts?.expiresAt ?? null);
77
- const newId = result.lastInsertRowid;
78
- // Mark previous active entry as superseded by this new version
79
- if (existing) {
80
- this.db.prepare('UPDATE knowledge SET superseded_by = ?, updated_at = ? WHERE id = ?').run(newId, now, existing.id);
81
- // Link: new version supersedes old version
82
- this.addLink(newId, existing.id, 'supersedes');
83
- }
84
- return {
85
- id: newId,
86
- agentId,
87
- domain,
88
- key,
89
- content,
90
- confidence,
91
- sourceType,
92
- sourceRef: opts?.sourceRef ?? null,
93
- createdAt: now,
94
- updatedAt: now,
95
- expiresAt: opts?.expiresAt ?? null,
96
- supersededBy: null,
97
- };
98
- }
99
- /**
100
- * Get current (non-superseded) knowledge for an agent.
101
- */
102
- getActive(agentId, opts) {
103
- let sql = `
104
- SELECT * FROM knowledge
105
- WHERE agent_id = ?
106
- AND superseded_by IS NULL
107
- AND (expires_at IS NULL OR expires_at > datetime('now'))
108
- `;
109
- const params = [agentId];
110
- if (opts?.domain) {
111
- sql += ' AND domain = ?';
112
- params.push(opts.domain);
113
- }
114
- sql += ' ORDER BY domain, key';
115
- if (opts?.limit) {
116
- sql += ' LIMIT ?';
117
- params.push(opts.limit);
118
- }
119
- const rows = this.db.prepare(sql).all(...params);
120
- return rows.map(parseKnowledgeRow);
121
- }
122
- /**
123
- * Get a specific knowledge entry by domain + key.
124
- */
125
- get(agentId, domain, key) {
126
- const row = this.db.prepare(`
127
- SELECT * FROM knowledge
128
- WHERE agent_id = ? AND domain = ? AND key = ?
129
- AND superseded_by IS NULL
130
- `).get(agentId, domain, key);
131
- return row ? parseKnowledgeRow(row) : null;
132
- }
133
- /**
134
- * Get the version history of a knowledge entry.
135
- */
136
- getHistory(agentId, domain, key) {
137
- const rows = this.db.prepare(`
138
- SELECT * FROM knowledge
139
- WHERE agent_id = ? AND domain = ? AND key = ?
140
- ORDER BY created_at DESC
141
- `).all(agentId, domain, key);
142
- return rows.map(parseKnowledgeRow);
143
- }
144
- /**
145
- * Search knowledge by content.
146
- */
147
- search(agentId, query, limit = 20) {
148
- const rows = this.db.prepare(`
149
- SELECT * FROM knowledge
150
- WHERE agent_id = ?
151
- AND superseded_by IS NULL
152
- AND (content LIKE ? OR key LIKE ?)
153
- ORDER BY confidence DESC
154
- LIMIT ?
155
- `).all(agentId, `%${query}%`, `%${query}%`, limit);
156
- return rows.map(parseKnowledgeRow);
157
- }
158
- /**
159
- * List all domains for an agent.
160
- */
161
- getDomains(agentId) {
162
- const rows = this.db.prepare(`
163
- SELECT DISTINCT domain FROM knowledge
164
- WHERE agent_id = ? AND superseded_by IS NULL
165
- ORDER BY domain
166
- `).all(agentId);
167
- return rows.map(r => r.domain);
168
- }
169
- /**
170
- * Add a link between knowledge entries.
171
- */
172
- addLink(fromId, toId, linkType) {
173
- this.db.prepare(`
174
- INSERT OR IGNORE INTO knowledge_links (from_type, from_id, to_type, to_id, link_type, created_at)
175
- VALUES ('knowledge', ?, 'knowledge', ?, ?, ?)
176
- `).run(fromId, toId, linkType, nowIso());
177
- }
178
- /**
179
- * Get knowledge count.
180
- */
181
- getCount(agentId) {
182
- const row = this.db.prepare('SELECT COUNT(*) AS count FROM knowledge WHERE agent_id = ? AND superseded_by IS NULL').get(agentId);
183
- return row.count;
184
- }
185
- /**
186
- * Import from MEMORY.md content.
187
- * Parses markdown sections into domain/key/content entries.
188
- */
189
- importFromMarkdown(agentId, markdown, sourcePath) {
190
- const lines = markdown.split('\n');
191
- let currentDomain = 'general';
192
- let currentKey = '';
193
- let currentContent = [];
194
- let imported = 0;
195
- const flush = () => {
196
- if (currentKey && currentContent.length > 0) {
197
- this.upsert(agentId, currentDomain, currentKey, currentContent.join('\n').trim(), {
198
- sourceType: 'manual',
199
- sourceRef: sourcePath,
200
- });
201
- imported++;
202
- }
203
- currentContent = [];
204
- };
205
- for (const line of lines) {
206
- // ## Section = domain
207
- if (line.startsWith('## ')) {
208
- flush();
209
- currentDomain = line.replace('## ', '').trim().toLowerCase().replace(/\s+/g, '_');
210
- currentKey = '';
211
- continue;
212
- }
213
- // ### Subsection or **Bold** = key
214
- if (line.startsWith('### ')) {
215
- flush();
216
- currentKey = line.replace('### ', '').trim();
217
- continue;
218
- }
219
- // - **Key:** Value pattern
220
- const kvMatch = line.match(/^[-*]\s+\*\*(.+?)\*\*[:\s]+(.+)/);
221
- if (kvMatch) {
222
- flush();
223
- currentKey = kvMatch[1].trim();
224
- currentContent.push(kvMatch[2].trim());
225
- continue;
226
- }
227
- // Regular content line
228
- if (currentKey) {
229
- currentContent.push(line);
230
- }
231
- else if (line.trim()) {
232
- // Content without a key — use line hash as key
233
- currentKey = `note_${lines.indexOf(line)}`;
234
- currentContent.push(line);
235
- }
236
- }
237
- flush();
238
- return imported;
239
- }
240
- }
241
- //# sourceMappingURL=knowledge-store.js.map
@@ -1,22 +0,0 @@
1
- /**
2
- * HyperMem Library Schema — Fleet-Wide Structured Knowledge
3
- *
4
- * Single database: ~/.openclaw/hypermem/library.db
5
- * The "crown jewel" — durable, backed up, low-write-frequency.
6
- *
7
- * Collections:
8
- * 1. Library entries (versioned docs, specs, reference material)
9
- * 2. Facts (agent-learned truths)
10
- * 3. Preferences (behavioral patterns)
11
- * 4. Knowledge (structured domain knowledge, supersedable)
12
- * 5. Episodes (significant events)
13
- * 6. Fleet registry (agents, orgs)
14
- * 7. System registry (server state, config)
15
- * 8. Session registry (lifecycle tracking)
16
- * 9. Work items (fleet kanban)
17
- * 10. Topics (cross-session thread tracking)
18
- */
19
- import type { DatabaseSync } from 'node:sqlite';
20
- export declare const LIBRARY_SCHEMA_VERSION = 7;
21
- export declare function migrateLibrary(db: DatabaseSync): void;
22
- //# sourceMappingURL=library-schema.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"library-schema.d.ts","sourceRoot":"","sources":["../src/library-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,eAAO,MAAM,sBAAsB,IAAI,CAAC;AA4rBxC,wBAAgB,cAAc,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA8DrD"}