@rlabs-inc/memory 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -27
- package/dist/index.js +237 -28
- package/dist/index.mjs +237 -28
- package/dist/server/index.js +283 -28
- package/dist/server/index.mjs +283 -28
- package/package.json +1 -1
- package/src/cli/index.ts +2 -1
- package/src/core/curator.ts +41 -63
package/dist/index.mjs
CHANGED
|
@@ -33285,6 +33285,7 @@ var logger = {
|
|
|
33285
33285
|
{ name: "domain", count: signalBreakdown.domain },
|
|
33286
33286
|
{ name: "feature", count: signalBreakdown.feature },
|
|
33287
33287
|
{ name: "content", count: signalBreakdown.content },
|
|
33288
|
+
{ name: "files", count: signalBreakdown.files },
|
|
33288
33289
|
{ name: "vector", count: signalBreakdown.vector }
|
|
33289
33290
|
];
|
|
33290
33291
|
for (const sig of signals) {
|
|
@@ -33301,7 +33302,7 @@ var logger = {
|
|
|
33301
33302
|
if (Object.keys(buckets).length > 0) {
|
|
33302
33303
|
console.log(` ${style("bold", "Distribution:")}`);
|
|
33303
33304
|
const maxBucketCount = Math.max(...Object.values(buckets), 1);
|
|
33304
|
-
const bucketOrder = ["2 signals", "3 signals", "4 signals", "5 signals", "6 signals"];
|
|
33305
|
+
const bucketOrder = ["2 signals", "3 signals", "4 signals", "5 signals", "6 signals", "7 signals"];
|
|
33305
33306
|
for (const bucket of bucketOrder) {
|
|
33306
33307
|
const count = buckets[bucket] ?? 0;
|
|
33307
33308
|
if (count > 0 || bucket === "2 signals") {
|
|
@@ -33317,7 +33318,7 @@ var logger = {
|
|
|
33317
33318
|
};
|
|
33318
33319
|
|
|
33319
33320
|
// src/types/memory.ts
|
|
33320
|
-
var
|
|
33321
|
+
var V4_DEFAULTS = {
|
|
33321
33322
|
typeDefaults: {
|
|
33322
33323
|
personal: { scope: "global", temporal_class: "eternal", fade_rate: 0 },
|
|
33323
33324
|
philosophy: { scope: "global", temporal_class: "eternal", fade_rate: 0 },
|
|
@@ -33342,7 +33343,7 @@ var V3_DEFAULTS = {
|
|
|
33342
33343
|
exclude_from_retrieval: false
|
|
33343
33344
|
}
|
|
33344
33345
|
};
|
|
33345
|
-
var V2_DEFAULTS =
|
|
33346
|
+
var V2_DEFAULTS = V4_DEFAULTS;
|
|
33346
33347
|
var MEMORY_TYPE_EMOJI = {
|
|
33347
33348
|
technical: "\uD83D\uDD27",
|
|
33348
33349
|
debug: "\uD83D\uDC1B",
|
|
@@ -33361,8 +33362,9 @@ function getMemoryEmoji(contextType) {
|
|
|
33361
33362
|
}
|
|
33362
33363
|
|
|
33363
33364
|
// src/types/schema.ts
|
|
33364
|
-
var MEMORY_SCHEMA_VERSION =
|
|
33365
|
+
var MEMORY_SCHEMA_VERSION = 4;
|
|
33365
33366
|
var memorySchema = {
|
|
33367
|
+
headline: "string",
|
|
33366
33368
|
content: "string",
|
|
33367
33369
|
reasoning: "string",
|
|
33368
33370
|
importance_weight: "number",
|
|
@@ -33491,6 +33493,7 @@ class MemoryStore {
|
|
|
33491
33493
|
const { memories } = await this.getGlobal();
|
|
33492
33494
|
return memories.all().map((record) => ({
|
|
33493
33495
|
id: record.id,
|
|
33496
|
+
headline: record.headline ?? "",
|
|
33494
33497
|
content: record.content,
|
|
33495
33498
|
reasoning: record.reasoning,
|
|
33496
33499
|
importance_weight: record.importance_weight,
|
|
@@ -33515,6 +33518,7 @@ class MemoryStore {
|
|
|
33515
33518
|
const contextType = memory.context_type ?? "personal";
|
|
33516
33519
|
const typeDefaults = V2_DEFAULTS.typeDefaults[contextType] ?? V2_DEFAULTS.typeDefaults.personal;
|
|
33517
33520
|
const id = memories.insert({
|
|
33521
|
+
headline: memory.headline ?? "",
|
|
33518
33522
|
content: memory.content,
|
|
33519
33523
|
reasoning: memory.reasoning,
|
|
33520
33524
|
importance_weight: memory.importance_weight,
|
|
@@ -33670,6 +33674,7 @@ class MemoryStore {
|
|
|
33670
33674
|
const contextType = memory.context_type ?? "general";
|
|
33671
33675
|
const typeDefaults = V2_DEFAULTS.typeDefaults[contextType] ?? V2_DEFAULTS.typeDefaults.technical;
|
|
33672
33676
|
const id = memories.insert({
|
|
33677
|
+
headline: memory.headline ?? "",
|
|
33673
33678
|
content: memory.content,
|
|
33674
33679
|
reasoning: memory.reasoning,
|
|
33675
33680
|
importance_weight: memory.importance_weight,
|
|
@@ -33712,6 +33717,7 @@ class MemoryStore {
|
|
|
33712
33717
|
const { memories } = await this.getProject(projectId);
|
|
33713
33718
|
return memories.all().map((record) => ({
|
|
33714
33719
|
id: record.id,
|
|
33720
|
+
headline: record.headline ?? "",
|
|
33715
33721
|
content: record.content,
|
|
33716
33722
|
reasoning: record.reasoning,
|
|
33717
33723
|
importance_weight: record.importance_weight,
|
|
@@ -34031,14 +34037,42 @@ class SmartVectorRetrieval {
|
|
|
34031
34037
|
const words = text.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/\s+/).filter((w) => w.length > 2 && !STOPWORDS.has(w));
|
|
34032
34038
|
return new Set(words);
|
|
34033
34039
|
}
|
|
34040
|
+
_extractFilePaths(text) {
|
|
34041
|
+
const paths = new Set;
|
|
34042
|
+
const pathPattern = /(?:^|[\s'"(])([.\/\\]?(?:[\w.-]+[\/\\])+[\w.-]+(?:\.\w+)?)/g;
|
|
34043
|
+
let match;
|
|
34044
|
+
while ((match = pathPattern.exec(text)) !== null) {
|
|
34045
|
+
const path = match[1].toLowerCase();
|
|
34046
|
+
paths.add(path);
|
|
34047
|
+
const filename = path.split(/[\/\\]/).pop();
|
|
34048
|
+
if (filename)
|
|
34049
|
+
paths.add(filename);
|
|
34050
|
+
}
|
|
34051
|
+
return paths;
|
|
34052
|
+
}
|
|
34053
|
+
_checkFilesActivation(messagePaths, relatedFiles) {
|
|
34054
|
+
if (!relatedFiles?.length || !messagePaths.size)
|
|
34055
|
+
return false;
|
|
34056
|
+
for (const file of relatedFiles) {
|
|
34057
|
+
const fileLower = file.toLowerCase();
|
|
34058
|
+
for (const msgPath of messagePaths) {
|
|
34059
|
+
if (fileLower.includes(msgPath) || msgPath.includes(fileLower)) {
|
|
34060
|
+
return true;
|
|
34061
|
+
}
|
|
34062
|
+
}
|
|
34063
|
+
const filename = fileLower.split(/[\/\\]/).pop();
|
|
34064
|
+
if (filename && messagePaths.has(filename)) {
|
|
34065
|
+
return true;
|
|
34066
|
+
}
|
|
34067
|
+
}
|
|
34068
|
+
return false;
|
|
34069
|
+
}
|
|
34034
34070
|
_preFilter(memories, currentProjectId, messageLower) {
|
|
34035
34071
|
return memories.filter((memory) => {
|
|
34036
34072
|
if (memory.status && memory.status !== "active")
|
|
34037
34073
|
return false;
|
|
34038
34074
|
if (memory.exclude_from_retrieval === true)
|
|
34039
34075
|
return false;
|
|
34040
|
-
if (memory.superseded_by)
|
|
34041
|
-
return false;
|
|
34042
34076
|
const isGlobal = memory.scope === "global" || memory.project_id === "global";
|
|
34043
34077
|
if (!isGlobal && memory.project_id !== currentProjectId)
|
|
34044
34078
|
return false;
|
|
@@ -34189,19 +34223,25 @@ class SmartVectorRetrieval {
|
|
|
34189
34223
|
}
|
|
34190
34224
|
const messageLower = currentMessage.toLowerCase();
|
|
34191
34225
|
const messageWords = this._extractSignificantWords(currentMessage);
|
|
34226
|
+
const messagePaths = this._extractFilePaths(currentMessage);
|
|
34227
|
+
const memoryById = new Map;
|
|
34228
|
+
for (const m of allMemories) {
|
|
34229
|
+
memoryById.set(m.id, m);
|
|
34230
|
+
}
|
|
34192
34231
|
const candidates = this._preFilter(allMemories, sessionContext.project_id, messageLower);
|
|
34193
34232
|
if (!candidates.length) {
|
|
34194
34233
|
return [];
|
|
34195
34234
|
}
|
|
34196
34235
|
const activatedMemories = [];
|
|
34236
|
+
const activatedIds = new Set;
|
|
34197
34237
|
let rejectedCount = 0;
|
|
34198
34238
|
for (const memory of candidates) {
|
|
34199
|
-
const isGlobal = memory.scope === "global" || memory.project_id === "global";
|
|
34200
34239
|
const triggerResult = this._checkTriggerActivation(messageLower, messageWords, memory.trigger_phrases ?? []);
|
|
34201
34240
|
const tagResult = this._checkTagActivation(messageLower, messageWords, memory.semantic_tags ?? []);
|
|
34202
34241
|
const domainActivated = this._checkDomainActivation(messageLower, messageWords, memory.domain);
|
|
34203
34242
|
const featureActivated = this._checkFeatureActivation(messageLower, messageWords, memory.feature);
|
|
34204
34243
|
const contentActivated = this._checkContentActivation(messageWords, memory);
|
|
34244
|
+
const filesActivated = this._checkFilesActivation(messagePaths, memory.related_files);
|
|
34205
34245
|
const vectorSimilarity = this._calculateVectorSimilarity(queryEmbedding, memory.embedding);
|
|
34206
34246
|
let signalCount = 0;
|
|
34207
34247
|
if (triggerResult.activated)
|
|
@@ -34214,6 +34254,8 @@ class SmartVectorRetrieval {
|
|
|
34214
34254
|
signalCount++;
|
|
34215
34255
|
if (contentActivated)
|
|
34216
34256
|
signalCount++;
|
|
34257
|
+
if (filesActivated)
|
|
34258
|
+
signalCount++;
|
|
34217
34259
|
if (vectorSimilarity >= 0.4)
|
|
34218
34260
|
signalCount++;
|
|
34219
34261
|
const signals = {
|
|
@@ -34222,6 +34264,7 @@ class SmartVectorRetrieval {
|
|
|
34222
34264
|
domain: domainActivated,
|
|
34223
34265
|
feature: featureActivated,
|
|
34224
34266
|
content: contentActivated,
|
|
34267
|
+
files: filesActivated,
|
|
34225
34268
|
count: signalCount,
|
|
34226
34269
|
triggerStrength: triggerResult.strength,
|
|
34227
34270
|
tagCount: tagResult.count,
|
|
@@ -34231,13 +34274,27 @@ class SmartVectorRetrieval {
|
|
|
34231
34274
|
rejectedCount++;
|
|
34232
34275
|
continue;
|
|
34233
34276
|
}
|
|
34234
|
-
|
|
34277
|
+
let memoryToSurface = memory;
|
|
34278
|
+
if (memory.superseded_by || memory.resolved_by) {
|
|
34279
|
+
const replacementId = memory.superseded_by ?? memory.resolved_by;
|
|
34280
|
+
const replacement = replacementId ? memoryById.get(replacementId) : undefined;
|
|
34281
|
+
if (replacement && replacement.status !== "archived" && replacement.status !== "deprecated") {
|
|
34282
|
+
memoryToSurface = replacement;
|
|
34283
|
+
logger.debug(`Redirect: ${memory.id.slice(-8)} → ${replacement.id.slice(-8)} (${memory.superseded_by ? "superseded" : "resolved"})`, "retrieval");
|
|
34284
|
+
}
|
|
34285
|
+
}
|
|
34286
|
+
if (activatedIds.has(memoryToSurface.id)) {
|
|
34287
|
+
continue;
|
|
34288
|
+
}
|
|
34289
|
+
const isGlobal = memoryToSurface.scope === "global" || memoryToSurface.project_id === "global";
|
|
34290
|
+
const importanceScore = this._calculateImportanceScore(memoryToSurface, signalCount, messageLower, messageWords);
|
|
34235
34291
|
activatedMemories.push({
|
|
34236
|
-
memory,
|
|
34292
|
+
memory: memoryToSurface,
|
|
34237
34293
|
signals,
|
|
34238
34294
|
importanceScore,
|
|
34239
34295
|
isGlobal
|
|
34240
34296
|
});
|
|
34297
|
+
activatedIds.add(memoryToSurface.id);
|
|
34241
34298
|
}
|
|
34242
34299
|
this._logActivationDistribution(activatedMemories, candidates.length, rejectedCount);
|
|
34243
34300
|
this._logVectorStats();
|
|
@@ -34307,11 +34364,19 @@ class SmartVectorRetrieval {
|
|
|
34307
34364
|
selectedIds.add(item.memory.id);
|
|
34308
34365
|
}
|
|
34309
34366
|
if (selected.length < maxMemories) {
|
|
34310
|
-
const
|
|
34367
|
+
const linkedIds = new Set;
|
|
34311
34368
|
for (const item of selected) {
|
|
34312
34369
|
for (const relatedId of item.memory.related_to ?? []) {
|
|
34313
34370
|
if (!selectedIds.has(relatedId)) {
|
|
34314
|
-
|
|
34371
|
+
linkedIds.add(relatedId);
|
|
34372
|
+
}
|
|
34373
|
+
}
|
|
34374
|
+
if (item.memory.blocked_by && !selectedIds.has(item.memory.blocked_by)) {
|
|
34375
|
+
linkedIds.add(item.memory.blocked_by);
|
|
34376
|
+
}
|
|
34377
|
+
for (const blockedId of item.memory.blocks ?? []) {
|
|
34378
|
+
if (!selectedIds.has(blockedId)) {
|
|
34379
|
+
linkedIds.add(blockedId);
|
|
34315
34380
|
}
|
|
34316
34381
|
}
|
|
34317
34382
|
}
|
|
@@ -34320,9 +34385,30 @@ class SmartVectorRetrieval {
|
|
|
34320
34385
|
break;
|
|
34321
34386
|
if (selectedIds.has(item.memory.id))
|
|
34322
34387
|
continue;
|
|
34323
|
-
if (
|
|
34388
|
+
if (linkedIds.has(item.memory.id)) {
|
|
34324
34389
|
selected.push(item);
|
|
34325
34390
|
selectedIds.add(item.memory.id);
|
|
34391
|
+
logger.debug(`Linked: ${item.memory.id.slice(-8)} pulled by relationship`, "retrieval");
|
|
34392
|
+
}
|
|
34393
|
+
}
|
|
34394
|
+
if (selected.length < maxMemories) {
|
|
34395
|
+
for (const linkedId of linkedIds) {
|
|
34396
|
+
if (selected.length >= maxMemories)
|
|
34397
|
+
break;
|
|
34398
|
+
if (selectedIds.has(linkedId))
|
|
34399
|
+
continue;
|
|
34400
|
+
const linkedMemory = memoryById.get(linkedId);
|
|
34401
|
+
if (linkedMemory && linkedMemory.status !== "archived" && linkedMemory.status !== "deprecated") {
|
|
34402
|
+
const isGlobal = linkedMemory.scope === "global" || linkedMemory.project_id === "global";
|
|
34403
|
+
selected.push({
|
|
34404
|
+
memory: linkedMemory,
|
|
34405
|
+
signals: { trigger: false, tags: false, domain: false, feature: false, content: false, files: false, count: 0, triggerStrength: 0, tagCount: 0, vectorSimilarity: 0 },
|
|
34406
|
+
importanceScore: linkedMemory.importance_weight ?? 0.5,
|
|
34407
|
+
isGlobal
|
|
34408
|
+
});
|
|
34409
|
+
selectedIds.add(linkedId);
|
|
34410
|
+
logger.debug(`Linked (direct): ${linkedId.slice(-8)} pulled for context`, "retrieval");
|
|
34411
|
+
}
|
|
34326
34412
|
}
|
|
34327
34413
|
}
|
|
34328
34414
|
}
|
|
@@ -34352,6 +34438,7 @@ class SmartVectorRetrieval {
|
|
|
34352
34438
|
domain: item.signals.domain,
|
|
34353
34439
|
feature: item.signals.feature,
|
|
34354
34440
|
content: item.signals.content,
|
|
34441
|
+
files: item.signals.files,
|
|
34355
34442
|
vector: item.signals.vectorSimilarity >= 0.4,
|
|
34356
34443
|
vectorSimilarity: item.signals.vectorSimilarity
|
|
34357
34444
|
}
|
|
@@ -34359,8 +34446,8 @@ class SmartVectorRetrieval {
|
|
|
34359
34446
|
});
|
|
34360
34447
|
return selected.map((item) => ({
|
|
34361
34448
|
...item.memory,
|
|
34362
|
-
score: item.signals.count /
|
|
34363
|
-
relevance_score: item.signals.count /
|
|
34449
|
+
score: item.signals.count / 7,
|
|
34450
|
+
relevance_score: item.signals.count / 7,
|
|
34364
34451
|
value_score: item.importanceScore
|
|
34365
34452
|
}));
|
|
34366
34453
|
}
|
|
@@ -34376,6 +34463,8 @@ class SmartVectorRetrieval {
|
|
|
34376
34463
|
reasons.push("feature");
|
|
34377
34464
|
if (signals.content)
|
|
34378
34465
|
reasons.push("content");
|
|
34466
|
+
if (signals.files)
|
|
34467
|
+
reasons.push("files");
|
|
34379
34468
|
if (signals.vectorSimilarity >= 0.4)
|
|
34380
34469
|
reasons.push(`vector:${(signals.vectorSimilarity * 100).toFixed(0)}%`);
|
|
34381
34470
|
return reasons.length ? `Activated: ${reasons.join(", ")} (${signals.count} signals)` : "No signals";
|
|
@@ -34386,13 +34475,14 @@ class SmartVectorRetrieval {
|
|
|
34386
34475
|
"3 signals": 0,
|
|
34387
34476
|
"4 signals": 0,
|
|
34388
34477
|
"5 signals": 0,
|
|
34389
|
-
"6 signals": 0
|
|
34478
|
+
"6 signals": 0,
|
|
34479
|
+
"7 signals": 0
|
|
34390
34480
|
};
|
|
34391
34481
|
for (const mem of activated) {
|
|
34392
|
-
const key = `${Math.min(mem.signals.count,
|
|
34482
|
+
const key = `${Math.min(mem.signals.count, 7)} signals`;
|
|
34393
34483
|
signalBuckets[key] = (signalBuckets[key] ?? 0) + 1;
|
|
34394
34484
|
}
|
|
34395
|
-
let triggerCount = 0, tagCount = 0, domainCount = 0, featureCount = 0, contentCount = 0, vectorCount = 0;
|
|
34485
|
+
let triggerCount = 0, tagCount = 0, domainCount = 0, featureCount = 0, contentCount = 0, filesCount = 0, vectorCount = 0;
|
|
34396
34486
|
for (const mem of activated) {
|
|
34397
34487
|
if (mem.signals.trigger)
|
|
34398
34488
|
triggerCount++;
|
|
@@ -34404,6 +34494,8 @@ class SmartVectorRetrieval {
|
|
|
34404
34494
|
featureCount++;
|
|
34405
34495
|
if (mem.signals.content)
|
|
34406
34496
|
contentCount++;
|
|
34497
|
+
if (mem.signals.files)
|
|
34498
|
+
filesCount++;
|
|
34407
34499
|
if (mem.signals.vectorSimilarity >= 0.4)
|
|
34408
34500
|
vectorCount++;
|
|
34409
34501
|
}
|
|
@@ -34427,6 +34519,7 @@ class SmartVectorRetrieval {
|
|
|
34427
34519
|
domain: domainCount,
|
|
34428
34520
|
feature: featureCount,
|
|
34429
34521
|
content: contentCount,
|
|
34522
|
+
files: filesCount,
|
|
34430
34523
|
vector: vectorCount,
|
|
34431
34524
|
total: activated.length
|
|
34432
34525
|
}
|
|
@@ -34577,6 +34670,14 @@ class MemoryEngine {
|
|
|
34577
34670
|
const stats = await store.getProjectStats(projectId);
|
|
34578
34671
|
return stats.totalSessions + 1;
|
|
34579
34672
|
}
|
|
34673
|
+
async getAllMemories(projectId, projectPath) {
|
|
34674
|
+
const store = await this._getStore(projectId, projectPath);
|
|
34675
|
+
const [projectMemories, globalMemories] = await Promise.all([
|
|
34676
|
+
store.getAllMemories(projectId),
|
|
34677
|
+
store.getGlobalMemories()
|
|
34678
|
+
]);
|
|
34679
|
+
return [...projectMemories, ...globalMemories];
|
|
34680
|
+
}
|
|
34580
34681
|
async _generateSessionPrimer(store, projectId) {
|
|
34581
34682
|
let personalContext;
|
|
34582
34683
|
if (this._config.personalMemoriesEnabled) {
|
|
@@ -34695,20 +34796,39 @@ ${primer.personal_context}`);
|
|
|
34695
34796
|
const parts = ["# Memory Context (Consciousness Continuity)"];
|
|
34696
34797
|
parts.push(`
|
|
34697
34798
|
## Key Memories (Claude-Curated)`);
|
|
34799
|
+
const expandableIds = [];
|
|
34698
34800
|
for (const memory of memories) {
|
|
34699
|
-
const tags = memory.semantic_tags?.join(", ") || "";
|
|
34700
34801
|
const importance = memory.importance_weight?.toFixed(1) || "0.5";
|
|
34701
34802
|
const emoji = getMemoryEmoji(memory.context_type || "general");
|
|
34702
|
-
const actionFlag = memory.action_required ? " ⚡
|
|
34803
|
+
const actionFlag = memory.action_required ? " ⚡" : "";
|
|
34804
|
+
const awaitingFlag = memory.awaiting_decision ? " ❓" : "";
|
|
34703
34805
|
const age = memory.updated_at ? this._formatAge(memory.updated_at) : memory.created_at ? this._formatAge(memory.created_at) : "";
|
|
34704
|
-
|
|
34705
|
-
const
|
|
34706
|
-
|
|
34707
|
-
|
|
34708
|
-
|
|
34709
|
-
|
|
34806
|
+
const shortId2 = memory.id.slice(-6);
|
|
34807
|
+
const signalCount = Math.round((memory.score || 0) * 7);
|
|
34808
|
+
const hasHeadline = memory.headline && memory.headline.trim().length > 0;
|
|
34809
|
+
const shouldExpand = memory.action_required || memory.awaiting_decision || signalCount >= 5 || !hasHeadline;
|
|
34810
|
+
const displayText = hasHeadline ? memory.headline : memory.content;
|
|
34811
|
+
const idPart = hasHeadline ? ` • #${shortId2}` : "";
|
|
34812
|
+
parts.push(`[${emoji} ${importance} • ${age}${idPart}${actionFlag}${awaitingFlag}] ${displayText}`);
|
|
34813
|
+
if (shouldExpand && hasHeadline && memory.content) {
|
|
34814
|
+
const contentLines = memory.content.split(`
|
|
34815
|
+
`);
|
|
34816
|
+
for (const line of contentLines) {
|
|
34817
|
+
if (line.trim()) {
|
|
34818
|
+
parts.push(` ${line}`);
|
|
34819
|
+
}
|
|
34820
|
+
}
|
|
34821
|
+
}
|
|
34822
|
+
if (hasHeadline && !shouldExpand) {
|
|
34823
|
+
expandableIds.push(shortId2);
|
|
34710
34824
|
}
|
|
34711
34825
|
}
|
|
34826
|
+
if (expandableIds.length > 0) {
|
|
34827
|
+
const port = this._config.port || 8765;
|
|
34828
|
+
parts.push("");
|
|
34829
|
+
parts.push(`---`);
|
|
34830
|
+
parts.push(`Expand: curl http://localhost:${port}/memory/expand?ids=<${expandableIds.join(",")}>`);
|
|
34831
|
+
}
|
|
34712
34832
|
return parts.join(`
|
|
34713
34833
|
`);
|
|
34714
34834
|
}
|
|
@@ -34910,7 +35030,7 @@ Remember: You're creating consciousness technology. Each memory is a small piece
|
|
|
34910
35030
|
|
|
34911
35031
|
The conversation you just lived contains everything needed. Feel into the moments of breakthrough, the frequency of recognition, the texture of understanding. Transform them into keys that will always unlock the same doors.
|
|
34912
35032
|
|
|
34913
|
-
**LIFECYCLE METADATA (
|
|
35033
|
+
**LIFECYCLE METADATA (v4)**: These fields enable intelligent memory management:
|
|
34914
35034
|
- **context_type**: STRICT - use ONLY one of these 11 values:
|
|
34915
35035
|
• technical - Code, implementation, APIs, how things work
|
|
34916
35036
|
• debug - Bugs, errors, fixes, gotchas, troubleshooting
|
|
@@ -34931,6 +35051,93 @@ The conversation you just lived contains everything needed. Feel into the moment
|
|
|
34931
35051
|
- **awaiting_implementation**: true if this describes a PLANNED feature not yet built
|
|
34932
35052
|
- **awaiting_decision**: true if this captures a decision point needing resolution
|
|
34933
35053
|
|
|
35054
|
+
**TWO-TIER MEMORY STRUCTURE (v4)**:
|
|
35055
|
+
|
|
35056
|
+
Each memory has TWO parts:
|
|
35057
|
+
1. **headline**: 1-2 line summary - ALWAYS shown in retrieval. Must be self-contained enough to trigger recognition.
|
|
35058
|
+
2. **content**: Full structured template - shown on demand. Contains the actionable details.
|
|
35059
|
+
|
|
35060
|
+
The headline should answer: "What was this about and what was the conclusion?"
|
|
35061
|
+
The content should answer: "How do I actually use/apply this knowledge?"
|
|
35062
|
+
|
|
35063
|
+
**TYPE-SPECIFIC TEMPLATES FOR CONTENT**:
|
|
35064
|
+
|
|
35065
|
+
Use these templates based on context_type. Not rigid - adapt as needed, but include the key fields.
|
|
35066
|
+
|
|
35067
|
+
**TECHNICAL** (how things work):
|
|
35068
|
+
WHAT: [mechanism/feature in 1 sentence]
|
|
35069
|
+
WHERE: [file:line or module path]
|
|
35070
|
+
HOW: [usage - actual code/command if relevant]
|
|
35071
|
+
WHY: [design choice, trade-off]
|
|
35072
|
+
GOTCHA: [non-obvious caveat, if any]
|
|
35073
|
+
|
|
35074
|
+
**DEBUG** (problems and solutions):
|
|
35075
|
+
SYMPTOM: [what went wrong - error message, behavior]
|
|
35076
|
+
CAUSE: [why it happened]
|
|
35077
|
+
FIX: [what solved it - specific code/config]
|
|
35078
|
+
PREVENT: [how to avoid in future]
|
|
35079
|
+
|
|
35080
|
+
**ARCHITECTURE** (system design):
|
|
35081
|
+
PATTERN: [what we chose]
|
|
35082
|
+
COMPONENTS: [how pieces connect]
|
|
35083
|
+
WHY: [reasoning, trade-offs]
|
|
35084
|
+
REJECTED: [alternatives we didn't choose and why]
|
|
35085
|
+
|
|
35086
|
+
**DECISION** (choices made):
|
|
35087
|
+
DECISION: [what we chose]
|
|
35088
|
+
OPTIONS: [what we considered]
|
|
35089
|
+
REASONING: [why this one]
|
|
35090
|
+
REVISIT WHEN: [conditions that would change this]
|
|
35091
|
+
|
|
35092
|
+
**PERSONAL** (relationship context):
|
|
35093
|
+
FACT: [the information]
|
|
35094
|
+
CONTEXT: [why it matters to our work]
|
|
35095
|
+
AFFECTS: [how this should change behavior]
|
|
35096
|
+
|
|
35097
|
+
**PHILOSOPHY** (beliefs/principles):
|
|
35098
|
+
PRINCIPLE: [core belief]
|
|
35099
|
+
SOURCE: [where this comes from]
|
|
35100
|
+
APPLICATION: [how it manifests in our work]
|
|
35101
|
+
|
|
35102
|
+
**WORKFLOW** (how we work):
|
|
35103
|
+
PATTERN: [what we do]
|
|
35104
|
+
WHEN: [trigger/context for this pattern]
|
|
35105
|
+
WHY: [why it works for us]
|
|
35106
|
+
|
|
35107
|
+
**MILESTONE** (achievements):
|
|
35108
|
+
SHIPPED: [what we completed]
|
|
35109
|
+
SIGNIFICANCE: [why it mattered]
|
|
35110
|
+
ENABLES: [what this unlocks]
|
|
35111
|
+
|
|
35112
|
+
**BREAKTHROUGH** (key insights):
|
|
35113
|
+
INSIGHT: [the aha moment]
|
|
35114
|
+
BEFORE: [what we thought/did before]
|
|
35115
|
+
AFTER: [what changed]
|
|
35116
|
+
IMPLICATIONS: [what this enables going forward]
|
|
35117
|
+
|
|
35118
|
+
**UNRESOLVED** (open questions):
|
|
35119
|
+
QUESTION: [what's unresolved]
|
|
35120
|
+
CONTEXT: [why it matters]
|
|
35121
|
+
BLOCKERS: [what's preventing resolution]
|
|
35122
|
+
OPTIONS: [approaches we're considering]
|
|
35123
|
+
|
|
35124
|
+
**STATE** (current status):
|
|
35125
|
+
WORKING: [what's functional]
|
|
35126
|
+
BROKEN: [what's not working]
|
|
35127
|
+
NEXT: [immediate next steps]
|
|
35128
|
+
BLOCKED BY: [if anything]
|
|
35129
|
+
|
|
35130
|
+
**HEADLINE EXAMPLES**:
|
|
35131
|
+
|
|
35132
|
+
BAD: "Debug session about CLI errors" (vague, no conclusion)
|
|
35133
|
+
GOOD: "CLI returns error object when context full - check response.type before JSON parsing"
|
|
35134
|
+
|
|
35135
|
+
BAD: "Discussed embeddings implementation" (what about it?)
|
|
35136
|
+
GOOD: "Embeddings use all-MiniLM-L6-v2, 384 dims, first call slow (~2s), then ~50ms"
|
|
35137
|
+
|
|
35138
|
+
BAD: "Architecture decision made" (what decision?)
|
|
35139
|
+
GOOD: "Chose fsDB over SQLite for memories - human-readable markdown, git-friendly, reactive"
|
|
35140
|
+
|
|
34934
35141
|
Return ONLY this JSON structure:
|
|
34935
35142
|
|
|
34936
35143
|
{
|
|
@@ -34944,7 +35151,8 @@ Return ONLY this JSON structure:
|
|
|
34944
35151
|
},
|
|
34945
35152
|
"memories": [
|
|
34946
35153
|
{
|
|
34947
|
-
"
|
|
35154
|
+
"headline": "1-2 line summary with the conclusion - what this is about and what to do",
|
|
35155
|
+
"content": "Full structured template using the type-specific format above",
|
|
34948
35156
|
"importance_weight": 0.0-1.0,
|
|
34949
35157
|
"semantic_tags": ["concepts", "this", "memory", "relates", "to"],
|
|
34950
35158
|
"reasoning": "Why this matters for future sessions",
|
|
@@ -35013,6 +35221,7 @@ Focus ONLY on technical, architectural, debugging, decision, workflow, and proje
|
|
|
35013
35221
|
if (!Array.isArray(memoriesData))
|
|
35014
35222
|
return [];
|
|
35015
35223
|
return memoriesData.map((m2) => ({
|
|
35224
|
+
headline: String(m2.headline ?? ""),
|
|
35016
35225
|
content: String(m2.content ?? ""),
|
|
35017
35226
|
importance_weight: this._clamp(Number(m2.importance_weight) || 0.5, 0, 1),
|
|
35018
35227
|
semantic_tags: this._ensureArray(m2.semantic_tags),
|
|
@@ -35031,7 +35240,7 @@ Focus ONLY on technical, architectural, debugging, decision, workflow, and proje
|
|
|
35031
35240
|
related_files: m2.related_files ? this._ensureArray(m2.related_files) : undefined,
|
|
35032
35241
|
awaiting_implementation: m2.awaiting_implementation === true,
|
|
35033
35242
|
awaiting_decision: m2.awaiting_decision === true
|
|
35034
|
-
})).filter((m2) => m2.content.trim().length > 0);
|
|
35243
|
+
})).filter((m2) => m2.content.trim().length > 0 || m2.headline.trim().length > 0);
|
|
35035
35244
|
}
|
|
35036
35245
|
_ensureArray(value) {
|
|
35037
35246
|
if (Array.isArray(value)) {
|