@rlabs-inc/memory 0.1.0 ā 0.2.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/dist/index.js +130 -18
- package/dist/index.mjs +130 -18
- package/dist/server/index.js +141 -18
- package/dist/server/index.mjs +141 -18
- package/hooks/curation.ts +89 -0
- package/hooks/session-start.ts +98 -0
- package/hooks/user-prompt.ts +97 -0
- package/package.json +14 -8
- package/src/cli/colors.ts +174 -0
- package/src/cli/commands/doctor.ts +143 -0
- package/src/cli/commands/install.ts +153 -0
- package/src/cli/commands/serve.ts +76 -0
- package/src/cli/commands/stats.ts +64 -0
- package/src/cli/index.ts +128 -0
- package/src/core/curator.ts +7 -48
- package/src/core/engine.test.ts +321 -0
- package/src/core/engine.ts +45 -8
- package/src/core/retrieval.ts +1 -1
- package/src/core/store.ts +109 -98
- package/src/server/index.ts +15 -40
- package/src/types/schema.ts +1 -1
- package/src/utils/logger.ts +158 -107
- package/bun.lock +0 -102
- package/test-retrieval.ts +0 -91
- package/tsconfig.json +0 -16
package/src/core/store.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// ============================================================================
|
|
2
|
-
// MEMORY STORE -
|
|
2
|
+
// MEMORY STORE - fsDB-powered storage
|
|
3
3
|
// Per-project database management with reactive parallel arrays
|
|
4
4
|
// ============================================================================
|
|
5
5
|
|
|
6
|
-
import { createDatabase, type Database } from '
|
|
6
|
+
import { createDatabase, type Database, type PersistentCollection } from '@rlabs-inc/fsdb'
|
|
7
7
|
import { homedir } from 'os'
|
|
8
8
|
import { join } from 'path'
|
|
9
9
|
import type {
|
|
@@ -42,21 +42,22 @@ export interface StoreConfig {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
|
-
* Project database
|
|
45
|
+
* Project database with collections
|
|
46
46
|
*/
|
|
47
|
-
interface
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
interface ProjectDB {
|
|
48
|
+
db: Database
|
|
49
|
+
memories: PersistentCollection<typeof memorySchema>
|
|
50
|
+
summaries: PersistentCollection<typeof sessionSummarySchema>
|
|
51
|
+
snapshots: PersistentCollection<typeof projectSnapshotSchema>
|
|
52
|
+
sessions: PersistentCollection<typeof sessionSchema>
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
/**
|
|
55
|
-
* MemoryStore - Manages per-project
|
|
56
|
+
* MemoryStore - Manages per-project fsDB instances
|
|
56
57
|
*/
|
|
57
58
|
export class MemoryStore {
|
|
58
59
|
private _config: Required<StoreConfig>
|
|
59
|
-
private _projects = new Map<string,
|
|
60
|
+
private _projects = new Map<string, ProjectDB>()
|
|
60
61
|
|
|
61
62
|
constructor(config: StoreConfig = {}) {
|
|
62
63
|
this._config = {
|
|
@@ -66,9 +67,9 @@ export class MemoryStore {
|
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
/**
|
|
69
|
-
* Get or create
|
|
70
|
+
* Get or create database for a project
|
|
70
71
|
*/
|
|
71
|
-
async getProject(projectId: string): Promise<
|
|
72
|
+
async getProject(projectId: string): Promise<ProjectDB> {
|
|
72
73
|
if (this._projects.has(projectId)) {
|
|
73
74
|
console.log(`š [DEBUG] Returning cached databases for ${projectId}`)
|
|
74
75
|
return this._projects.get(projectId)!
|
|
@@ -78,40 +79,51 @@ export class MemoryStore {
|
|
|
78
79
|
const projectPath = join(this._config.basePath, projectId)
|
|
79
80
|
console.log(` Path: ${projectPath}`)
|
|
80
81
|
|
|
81
|
-
// Create
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
82
|
+
// Create the database for this project
|
|
83
|
+
const db = createDatabase({
|
|
84
|
+
name: projectId,
|
|
85
|
+
basePath: projectPath,
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
// Create all collections for this project
|
|
89
|
+
const memories = db.collection('memories', {
|
|
90
|
+
schema: memorySchema,
|
|
91
|
+
contentColumn: 'content',
|
|
92
|
+
autoSave: true,
|
|
93
|
+
watchFiles: this._config.watchFiles,
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
const summaries = db.collection('summaries', {
|
|
97
|
+
schema: sessionSummarySchema,
|
|
98
|
+
contentColumn: 'summary',
|
|
99
|
+
autoSave: true,
|
|
100
|
+
watchFiles: this._config.watchFiles,
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
const snapshots = db.collection('snapshots', {
|
|
104
|
+
schema: projectSnapshotSchema,
|
|
105
|
+
autoSave: true,
|
|
106
|
+
watchFiles: this._config.watchFiles,
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
const sessions = db.collection('sessions', {
|
|
110
|
+
schema: sessionSchema,
|
|
111
|
+
autoSave: true,
|
|
112
|
+
watchFiles: this._config.watchFiles,
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
// Load existing data
|
|
116
|
+
await Promise.all([
|
|
117
|
+
memories.load(),
|
|
118
|
+
summaries.load(),
|
|
119
|
+
snapshots.load(),
|
|
120
|
+
sessions.load(),
|
|
109
121
|
])
|
|
110
122
|
|
|
111
|
-
const
|
|
112
|
-
this._projects.set(projectId,
|
|
123
|
+
const projectDB: ProjectDB = { db, memories, summaries, snapshots, sessions }
|
|
124
|
+
this._projects.set(projectId, projectDB)
|
|
113
125
|
|
|
114
|
-
return
|
|
126
|
+
return projectDB
|
|
115
127
|
}
|
|
116
128
|
|
|
117
129
|
// ================================================================
|
|
@@ -129,7 +141,7 @@ export class MemoryStore {
|
|
|
129
141
|
): Promise<string> {
|
|
130
142
|
const { memories } = await this.getProject(projectId)
|
|
131
143
|
|
|
132
|
-
const id =
|
|
144
|
+
const id = memories.insert({
|
|
133
145
|
content: memory.content,
|
|
134
146
|
reasoning: memory.reasoning,
|
|
135
147
|
importance_weight: memory.importance_weight,
|
|
@@ -147,7 +159,7 @@ export class MemoryStore {
|
|
|
147
159
|
project_id: projectId,
|
|
148
160
|
embedding: embedding
|
|
149
161
|
? (embedding instanceof Float32Array ? embedding : new Float32Array(embedding))
|
|
150
|
-
:
|
|
162
|
+
: null,
|
|
151
163
|
})
|
|
152
164
|
|
|
153
165
|
return id
|
|
@@ -165,10 +177,10 @@ export class MemoryStore {
|
|
|
165
177
|
reasoning: record.reasoning,
|
|
166
178
|
importance_weight: record.importance_weight,
|
|
167
179
|
confidence_score: record.confidence_score,
|
|
168
|
-
context_type: record.context_type,
|
|
169
|
-
temporal_relevance: record.temporal_relevance,
|
|
170
|
-
knowledge_domain: record.knowledge_domain,
|
|
171
|
-
emotional_resonance: record.emotional_resonance,
|
|
180
|
+
context_type: record.context_type as StoredMemory['context_type'],
|
|
181
|
+
temporal_relevance: record.temporal_relevance as StoredMemory['temporal_relevance'],
|
|
182
|
+
knowledge_domain: record.knowledge_domain as StoredMemory['knowledge_domain'],
|
|
183
|
+
emotional_resonance: record.emotional_resonance as StoredMemory['emotional_resonance'],
|
|
172
184
|
action_required: record.action_required,
|
|
173
185
|
problem_solution_pair: record.problem_solution_pair,
|
|
174
186
|
semantic_tags: record.semantic_tags,
|
|
@@ -176,7 +188,7 @@ export class MemoryStore {
|
|
|
176
188
|
question_types: record.question_types,
|
|
177
189
|
session_id: record.session_id,
|
|
178
190
|
project_id: record.project_id,
|
|
179
|
-
embedding: record.embedding,
|
|
191
|
+
embedding: record.embedding ?? undefined,
|
|
180
192
|
created_at: record.created,
|
|
181
193
|
updated_at: record.updated,
|
|
182
194
|
stale: record.stale,
|
|
@@ -196,18 +208,19 @@ export class MemoryStore {
|
|
|
196
208
|
|
|
197
209
|
const results = memories.search('embedding', queryEmbedding, {
|
|
198
210
|
topK,
|
|
199
|
-
filter: filter ? (record) => {
|
|
200
|
-
//
|
|
211
|
+
filter: filter ? (record, _idx) => {
|
|
212
|
+
// Filter receives raw schema record - we need to adapt it
|
|
213
|
+
// Note: filter doesn't have access to id/created/updated (those are in RecordWithMeta)
|
|
201
214
|
const mem: StoredMemory = {
|
|
202
|
-
id:
|
|
215
|
+
id: '', // Not available in filter
|
|
203
216
|
content: record.content,
|
|
204
217
|
reasoning: record.reasoning,
|
|
205
218
|
importance_weight: record.importance_weight,
|
|
206
219
|
confidence_score: record.confidence_score,
|
|
207
|
-
context_type: record.context_type,
|
|
208
|
-
temporal_relevance: record.temporal_relevance,
|
|
209
|
-
knowledge_domain: record.knowledge_domain,
|
|
210
|
-
emotional_resonance: record.emotional_resonance,
|
|
220
|
+
context_type: record.context_type as StoredMemory['context_type'],
|
|
221
|
+
temporal_relevance: record.temporal_relevance as StoredMemory['temporal_relevance'],
|
|
222
|
+
knowledge_domain: record.knowledge_domain as StoredMemory['knowledge_domain'],
|
|
223
|
+
emotional_resonance: record.emotional_resonance as StoredMemory['emotional_resonance'],
|
|
211
224
|
action_required: record.action_required,
|
|
212
225
|
problem_solution_pair: record.problem_solution_pair,
|
|
213
226
|
semantic_tags: record.semantic_tags,
|
|
@@ -222,27 +235,27 @@ export class MemoryStore {
|
|
|
222
235
|
} : undefined,
|
|
223
236
|
})
|
|
224
237
|
|
|
225
|
-
return results.map(
|
|
226
|
-
id: record.id,
|
|
227
|
-
content: record.content,
|
|
228
|
-
reasoning: record.reasoning,
|
|
229
|
-
importance_weight: record.importance_weight,
|
|
230
|
-
confidence_score: record.confidence_score,
|
|
231
|
-
context_type: record.context_type,
|
|
232
|
-
temporal_relevance: record.temporal_relevance,
|
|
233
|
-
knowledge_domain: record.knowledge_domain,
|
|
234
|
-
emotional_resonance: record.emotional_resonance,
|
|
235
|
-
action_required: record.action_required,
|
|
236
|
-
problem_solution_pair: record.problem_solution_pair,
|
|
237
|
-
semantic_tags: record.semantic_tags,
|
|
238
|
-
trigger_phrases: record.trigger_phrases,
|
|
239
|
-
question_types: record.question_types,
|
|
240
|
-
session_id: record.session_id,
|
|
241
|
-
project_id: record.project_id,
|
|
242
|
-
embedding: record.embedding,
|
|
243
|
-
created_at: record.created,
|
|
244
|
-
updated_at: record.updated,
|
|
245
|
-
stale:
|
|
238
|
+
return results.map(result => ({
|
|
239
|
+
id: result.record.id,
|
|
240
|
+
content: result.record.content,
|
|
241
|
+
reasoning: result.record.reasoning,
|
|
242
|
+
importance_weight: result.record.importance_weight,
|
|
243
|
+
confidence_score: result.record.confidence_score,
|
|
244
|
+
context_type: result.record.context_type as StoredMemory['context_type'],
|
|
245
|
+
temporal_relevance: result.record.temporal_relevance as StoredMemory['temporal_relevance'],
|
|
246
|
+
knowledge_domain: result.record.knowledge_domain as StoredMemory['knowledge_domain'],
|
|
247
|
+
emotional_resonance: result.record.emotional_resonance as StoredMemory['emotional_resonance'],
|
|
248
|
+
action_required: result.record.action_required,
|
|
249
|
+
problem_solution_pair: result.record.problem_solution_pair,
|
|
250
|
+
semantic_tags: result.record.semantic_tags,
|
|
251
|
+
trigger_phrases: result.record.trigger_phrases,
|
|
252
|
+
question_types: result.record.question_types,
|
|
253
|
+
session_id: result.record.session_id,
|
|
254
|
+
project_id: result.record.project_id,
|
|
255
|
+
embedding: result.record.embedding ?? undefined,
|
|
256
|
+
created_at: result.record.created,
|
|
257
|
+
updated_at: result.record.updated,
|
|
258
|
+
stale: result.stale,
|
|
246
259
|
}))
|
|
247
260
|
}
|
|
248
261
|
|
|
@@ -254,9 +267,10 @@ export class MemoryStore {
|
|
|
254
267
|
memoryId: string,
|
|
255
268
|
embedding: Float32Array | number[],
|
|
256
269
|
content: string
|
|
257
|
-
): Promise<
|
|
270
|
+
): Promise<void> {
|
|
258
271
|
const { memories } = await this.getProject(projectId)
|
|
259
|
-
|
|
272
|
+
const vec = embedding instanceof Float32Array ? embedding : new Float32Array(embedding)
|
|
273
|
+
memories.setEmbedding(memoryId, 'embedding', vec, content)
|
|
260
274
|
}
|
|
261
275
|
|
|
262
276
|
/**
|
|
@@ -264,7 +278,7 @@ export class MemoryStore {
|
|
|
264
278
|
*/
|
|
265
279
|
async getStaleMemoryIds(projectId: string): Promise<string[]> {
|
|
266
280
|
const { memories } = await this.getProject(projectId)
|
|
267
|
-
return memories.
|
|
281
|
+
return memories.all().filter(r => r.stale).map(r => r.id)
|
|
268
282
|
}
|
|
269
283
|
|
|
270
284
|
// ================================================================
|
|
@@ -293,7 +307,7 @@ export class MemoryStore {
|
|
|
293
307
|
const allSessions = sessions.all()
|
|
294
308
|
const firstSessionCompleted = allSessions.some(s => s.first_session_completed)
|
|
295
309
|
|
|
296
|
-
|
|
310
|
+
sessions.insert({
|
|
297
311
|
id: sessionId,
|
|
298
312
|
project_id: projectId,
|
|
299
313
|
message_count: 0,
|
|
@@ -321,7 +335,7 @@ export class MemoryStore {
|
|
|
321
335
|
}
|
|
322
336
|
|
|
323
337
|
const newCount = session.message_count + 1
|
|
324
|
-
|
|
338
|
+
sessions.update(sessionId, {
|
|
325
339
|
message_count: newCount,
|
|
326
340
|
last_active: Date.now(),
|
|
327
341
|
})
|
|
@@ -334,7 +348,7 @@ export class MemoryStore {
|
|
|
334
348
|
*/
|
|
335
349
|
async markFirstSessionCompleted(projectId: string, sessionId: string): Promise<void> {
|
|
336
350
|
const { sessions } = await this.getProject(projectId)
|
|
337
|
-
|
|
351
|
+
sessions.update(sessionId, { first_session_completed: true })
|
|
338
352
|
}
|
|
339
353
|
|
|
340
354
|
// ================================================================
|
|
@@ -356,7 +370,7 @@ export class MemoryStore {
|
|
|
356
370
|
console.log(` Summary length: ${summary.length} chars`)
|
|
357
371
|
console.log(` Summaries count before: ${summaries.all().length}`)
|
|
358
372
|
|
|
359
|
-
const id =
|
|
373
|
+
const id = summaries.insert({
|
|
360
374
|
session_id: sessionId,
|
|
361
375
|
project_id: projectId,
|
|
362
376
|
summary,
|
|
@@ -385,9 +399,9 @@ export class MemoryStore {
|
|
|
385
399
|
}
|
|
386
400
|
|
|
387
401
|
// Sort by created timestamp (most recent first)
|
|
388
|
-
all.sort((a, b) => b.created - a.created)
|
|
402
|
+
const sorted = [...all].sort((a, b) => b.created - a.created)
|
|
389
403
|
|
|
390
|
-
const latest =
|
|
404
|
+
const latest = sorted[0]!
|
|
391
405
|
console.log(` Latest summary: ${latest.summary.slice(0, 50)}...`)
|
|
392
406
|
|
|
393
407
|
return {
|
|
@@ -434,9 +448,9 @@ export class MemoryStore {
|
|
|
434
448
|
if (!all.length) return null
|
|
435
449
|
|
|
436
450
|
// Sort by created timestamp (most recent first)
|
|
437
|
-
all.sort((a, b) => b.created - a.created)
|
|
451
|
+
const sorted = [...all].sort((a, b) => b.created - a.created)
|
|
438
452
|
|
|
439
|
-
const latest =
|
|
453
|
+
const latest = sorted[0]!
|
|
440
454
|
return {
|
|
441
455
|
id: latest.id,
|
|
442
456
|
session_id: latest.session_id,
|
|
@@ -466,19 +480,19 @@ export class MemoryStore {
|
|
|
466
480
|
|
|
467
481
|
const allMemories = memories.all()
|
|
468
482
|
const allSessions = sessions.all()
|
|
469
|
-
const
|
|
483
|
+
const staleCount = allMemories.filter(r => r.stale).length
|
|
470
484
|
|
|
471
485
|
// Find latest session
|
|
472
486
|
let latestSession: string | null = null
|
|
473
487
|
if (allSessions.length) {
|
|
474
|
-
allSessions.sort((a, b) => b.last_active - a.last_active)
|
|
475
|
-
latestSession =
|
|
488
|
+
const sorted = [...allSessions].sort((a, b) => b.last_active - a.last_active)
|
|
489
|
+
latestSession = sorted[0]!.id
|
|
476
490
|
}
|
|
477
491
|
|
|
478
492
|
return {
|
|
479
493
|
totalMemories: allMemories.length,
|
|
480
494
|
totalSessions: allSessions.length,
|
|
481
|
-
staleMemories:
|
|
495
|
+
staleMemories: staleCount,
|
|
482
496
|
latestSession,
|
|
483
497
|
}
|
|
484
498
|
}
|
|
@@ -487,11 +501,8 @@ export class MemoryStore {
|
|
|
487
501
|
* Close all project databases
|
|
488
502
|
*/
|
|
489
503
|
close(): void {
|
|
490
|
-
for (const
|
|
491
|
-
|
|
492
|
-
dbs.summaries.close()
|
|
493
|
-
dbs.snapshots.close()
|
|
494
|
-
dbs.sessions.close()
|
|
504
|
+
for (const projectDB of this._projects.values()) {
|
|
505
|
+
projectDB.db.close()
|
|
495
506
|
}
|
|
496
507
|
this._projects.clear()
|
|
497
508
|
}
|
package/src/server/index.ts
CHANGED
|
@@ -12,21 +12,8 @@ import { logger } from '../utils/logger.ts'
|
|
|
12
12
|
* Server configuration
|
|
13
13
|
*/
|
|
14
14
|
export interface ServerConfig extends EngineConfig {
|
|
15
|
-
/**
|
|
16
|
-
* Port to listen on
|
|
17
|
-
* Default: 8765 (same as Python)
|
|
18
|
-
*/
|
|
19
15
|
port?: number
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Host to bind to
|
|
23
|
-
* Default: 'localhost'
|
|
24
|
-
*/
|
|
25
16
|
host?: string
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Curator configuration
|
|
29
|
-
*/
|
|
30
17
|
curator?: CuratorConfig
|
|
31
18
|
}
|
|
32
19
|
|
|
@@ -61,7 +48,6 @@ interface CheckpointRequest {
|
|
|
61
48
|
|
|
62
49
|
/**
|
|
63
50
|
* Create and start the memory server
|
|
64
|
-
* Uses Bun.serve() for high performance
|
|
65
51
|
*/
|
|
66
52
|
export function createServer(config: ServerConfig = {}) {
|
|
67
53
|
const {
|
|
@@ -102,7 +88,9 @@ export function createServer(config: ServerConfig = {}) {
|
|
|
102
88
|
|
|
103
89
|
// Get memory context for a message
|
|
104
90
|
if (path === '/memory/context' && req.method === 'POST') {
|
|
105
|
-
const body
|
|
91
|
+
const body = await req.json() as ContextRequest
|
|
92
|
+
|
|
93
|
+
logger.request('POST', '/memory/context', body.project_id)
|
|
106
94
|
|
|
107
95
|
const result = await engine.getContext({
|
|
108
96
|
sessionId: body.session_id,
|
|
@@ -126,20 +114,13 @@ export function createServer(config: ServerConfig = {}) {
|
|
|
126
114
|
)
|
|
127
115
|
}
|
|
128
116
|
|
|
129
|
-
// Debug: show what's actually being returned
|
|
130
|
-
console.log(`\nš¤ [DEBUG] Response to hook:`)
|
|
131
|
-
console.log(` memories_count: ${result.memories.length}`)
|
|
132
|
-
console.log(` has_primer: ${!!result.primer}`)
|
|
133
|
-
console.log(` formatted length: ${result.formatted.length} chars`)
|
|
134
|
-
if (result.formatted) {
|
|
135
|
-
console.log(` formatted preview:\n${result.formatted.slice(0, 300)}...`)
|
|
136
|
-
} else {
|
|
137
|
-
console.log(` ā ļø formatted is EMPTY!`)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
117
|
return Response.json({
|
|
141
118
|
success: true,
|
|
142
|
-
|
|
119
|
+
session_id: body.session_id,
|
|
120
|
+
message_count: 0,
|
|
121
|
+
context_text: result.formatted,
|
|
122
|
+
has_memories: result.memories.length > 0,
|
|
123
|
+
curator_enabled: true,
|
|
143
124
|
memories_count: result.memories.length,
|
|
144
125
|
has_primer: !!result.primer,
|
|
145
126
|
}, { headers: corsHeaders })
|
|
@@ -147,7 +128,7 @@ export function createServer(config: ServerConfig = {}) {
|
|
|
147
128
|
|
|
148
129
|
// Process/track a message exchange
|
|
149
130
|
if (path === '/memory/process' && req.method === 'POST') {
|
|
150
|
-
const body
|
|
131
|
+
const body = await req.json() as ProcessRequest
|
|
151
132
|
|
|
152
133
|
const messageCount = await engine.trackMessage(
|
|
153
134
|
body.project_id,
|
|
@@ -155,7 +136,7 @@ export function createServer(config: ServerConfig = {}) {
|
|
|
155
136
|
body.project_path
|
|
156
137
|
)
|
|
157
138
|
|
|
158
|
-
logger.session(`Message #${messageCount} tracked
|
|
139
|
+
logger.session(`Message #${messageCount} tracked [${body.project_id}]`)
|
|
159
140
|
|
|
160
141
|
return Response.json({
|
|
161
142
|
success: true,
|
|
@@ -165,15 +146,13 @@ export function createServer(config: ServerConfig = {}) {
|
|
|
165
146
|
|
|
166
147
|
// Checkpoint - trigger curation
|
|
167
148
|
if (path === '/memory/checkpoint' && req.method === 'POST') {
|
|
168
|
-
const body
|
|
149
|
+
const body = await req.json() as CheckpointRequest
|
|
169
150
|
|
|
170
|
-
logger.
|
|
151
|
+
logger.logCurationStart(body.claude_session_id, body.trigger)
|
|
171
152
|
|
|
172
153
|
// Fire and forget - don't block the response
|
|
173
154
|
setImmediate(async () => {
|
|
174
155
|
try {
|
|
175
|
-
logger.info(`Resuming session ${body.claude_session_id.slice(0, 8)}... for curation`)
|
|
176
|
-
|
|
177
156
|
const result = await curator.curateWithCLI(
|
|
178
157
|
body.claude_session_id,
|
|
179
158
|
body.trigger,
|
|
@@ -188,14 +167,10 @@ export function createServer(config: ServerConfig = {}) {
|
|
|
188
167
|
body.project_path
|
|
189
168
|
)
|
|
190
169
|
|
|
170
|
+
logger.logCurationComplete(result.memories.length, result.session_summary)
|
|
191
171
|
logger.logCuratedMemories(result.memories)
|
|
192
|
-
logger.success(`Stored ${result.memories.length} memories for ${body.project_id}`)
|
|
193
|
-
|
|
194
|
-
if (result.session_summary) {
|
|
195
|
-
logger.info(`Summary: ${result.session_summary.slice(0, 100)}...`)
|
|
196
|
-
}
|
|
197
172
|
} else {
|
|
198
|
-
logger.
|
|
173
|
+
logger.logCurationComplete(0)
|
|
199
174
|
}
|
|
200
175
|
} catch (error) {
|
|
201
176
|
logger.error(`Curation failed: ${error}`)
|
|
@@ -227,7 +202,7 @@ export function createServer(config: ServerConfig = {}) {
|
|
|
227
202
|
{ status: 404, headers: corsHeaders }
|
|
228
203
|
)
|
|
229
204
|
} catch (error) {
|
|
230
|
-
|
|
205
|
+
logger.error(`Server error: ${error}`)
|
|
231
206
|
return Response.json(
|
|
232
207
|
{ error: String(error) },
|
|
233
208
|
{ status: 500, headers: corsHeaders }
|
package/src/types/schema.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Maps CuratedMemory to reactive parallel arrays
|
|
4
4
|
// ============================================================================
|
|
5
5
|
|
|
6
|
-
import type { SchemaDefinition } from '
|
|
6
|
+
import type { SchemaDefinition } from '@rlabs-inc/fsdb'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Memory storage schema
|