@rlabs-inc/memory 0.3.5 → 0.3.7
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 +129 -33
- package/dist/index.js +803 -179
- package/dist/index.mjs +803 -179
- package/dist/server/index.js +36774 -2643
- package/dist/server/index.mjs +1034 -185
- package/package.json +3 -2
- package/skills/memory-management.md +686 -0
- package/src/cli/commands/migrate.ts +423 -0
- package/src/cli/commands/serve.ts +88 -0
- package/src/cli/index.ts +21 -0
- package/src/core/curator.ts +151 -17
- package/src/core/engine.ts +159 -11
- package/src/core/manager.ts +484 -0
- package/src/core/retrieval.ts +547 -420
- package/src/core/store.ts +383 -8
- package/src/server/index.ts +108 -8
- package/src/types/memory.ts +142 -0
- package/src/types/schema.ts +80 -7
- package/src/utils/logger.ts +310 -46
package/dist/index.js
CHANGED
|
@@ -11995,7 +11995,60 @@ function createDatabase(options = {}) {
|
|
|
11995
11995
|
var import_os = require("os");
|
|
11996
11996
|
var import_path = require("path");
|
|
11997
11997
|
|
|
11998
|
+
// src/types/memory.ts
|
|
11999
|
+
var V2_DEFAULTS = {
|
|
12000
|
+
typeDefaults: {
|
|
12001
|
+
personal: { scope: "global", temporal_class: "eternal", fade_rate: 0 },
|
|
12002
|
+
philosophy: { scope: "global", temporal_class: "eternal", fade_rate: 0 },
|
|
12003
|
+
preference: { scope: "global", temporal_class: "long_term", fade_rate: 0.01 },
|
|
12004
|
+
breakthrough: { scope: "project", temporal_class: "eternal", fade_rate: 0 },
|
|
12005
|
+
decision: { scope: "project", temporal_class: "long_term", fade_rate: 0 },
|
|
12006
|
+
milestone: { scope: "project", temporal_class: "eternal", fade_rate: 0 },
|
|
12007
|
+
technical: { scope: "project", temporal_class: "medium_term", fade_rate: 0.03 },
|
|
12008
|
+
architectural: { scope: "project", temporal_class: "long_term", fade_rate: 0.01 },
|
|
12009
|
+
debugging: { scope: "project", temporal_class: "medium_term", fade_rate: 0.03 },
|
|
12010
|
+
unresolved: { scope: "project", temporal_class: "medium_term", fade_rate: 0.05 },
|
|
12011
|
+
todo: { scope: "project", temporal_class: "short_term", fade_rate: 0.1 },
|
|
12012
|
+
technical_state: { scope: "project", temporal_class: "short_term", fade_rate: 0.1 },
|
|
12013
|
+
workflow: { scope: "project", temporal_class: "long_term", fade_rate: 0.02 },
|
|
12014
|
+
project_context: { scope: "project", temporal_class: "medium_term", fade_rate: 0.03 }
|
|
12015
|
+
},
|
|
12016
|
+
fallback: {
|
|
12017
|
+
status: "active",
|
|
12018
|
+
scope: "project",
|
|
12019
|
+
temporal_class: "medium_term",
|
|
12020
|
+
fade_rate: 0.03,
|
|
12021
|
+
sessions_since_surfaced: 0,
|
|
12022
|
+
awaiting_implementation: false,
|
|
12023
|
+
awaiting_decision: false,
|
|
12024
|
+
exclude_from_retrieval: false
|
|
12025
|
+
}
|
|
12026
|
+
};
|
|
12027
|
+
var MEMORY_TYPE_EMOJI = {
|
|
12028
|
+
breakthrough: "\uD83D\uDCA1",
|
|
12029
|
+
decision: "⚖️",
|
|
12030
|
+
personal: "\uD83D\uDC9C",
|
|
12031
|
+
technical: "\uD83D\uDD27",
|
|
12032
|
+
technical_state: "\uD83D\uDCCD",
|
|
12033
|
+
unresolved: "❓",
|
|
12034
|
+
preference: "⚙️",
|
|
12035
|
+
workflow: "\uD83D\uDD04",
|
|
12036
|
+
architectural: "\uD83C\uDFD7️",
|
|
12037
|
+
debugging: "\uD83D\uDC1B",
|
|
12038
|
+
philosophy: "\uD83C\uDF00",
|
|
12039
|
+
todo: "\uD83C\uDFAF",
|
|
12040
|
+
implementation: "⚡",
|
|
12041
|
+
problem_solution: "✅",
|
|
12042
|
+
project_context: "\uD83D\uDCE6",
|
|
12043
|
+
milestone: "\uD83C\uDFC6",
|
|
12044
|
+
general: "\uD83D\uDCDD"
|
|
12045
|
+
};
|
|
12046
|
+
function getMemoryEmoji(contextType) {
|
|
12047
|
+
return MEMORY_TYPE_EMOJI[contextType.toLowerCase()] ?? "\uD83D\uDCDD";
|
|
12048
|
+
}
|
|
12049
|
+
|
|
11998
12050
|
// src/types/schema.ts
|
|
12051
|
+
var MEMORY_SCHEMA_VERSION = 2;
|
|
11999
12052
|
var memorySchema = {
|
|
12000
12053
|
content: "string",
|
|
12001
12054
|
reasoning: "string",
|
|
@@ -12012,7 +12065,34 @@ var memorySchema = {
|
|
|
12012
12065
|
question_types: "string[]",
|
|
12013
12066
|
session_id: "string",
|
|
12014
12067
|
project_id: "string",
|
|
12015
|
-
embedding: "vector:384"
|
|
12068
|
+
embedding: "vector:384",
|
|
12069
|
+
status: "string",
|
|
12070
|
+
scope: "string",
|
|
12071
|
+
session_created: "number",
|
|
12072
|
+
session_updated: "number",
|
|
12073
|
+
last_surfaced: "number",
|
|
12074
|
+
sessions_since_surfaced: "number",
|
|
12075
|
+
temporal_class: "string",
|
|
12076
|
+
fade_rate: "number",
|
|
12077
|
+
expires_after_sessions: "number",
|
|
12078
|
+
domain: "string",
|
|
12079
|
+
feature: "string",
|
|
12080
|
+
component: "string",
|
|
12081
|
+
supersedes: "string",
|
|
12082
|
+
superseded_by: "string",
|
|
12083
|
+
related_to: "string[]",
|
|
12084
|
+
resolves: "string[]",
|
|
12085
|
+
resolved_by: "string",
|
|
12086
|
+
parent_id: "string",
|
|
12087
|
+
child_ids: "string[]",
|
|
12088
|
+
awaiting_implementation: "boolean",
|
|
12089
|
+
awaiting_decision: "boolean",
|
|
12090
|
+
blocked_by: "string",
|
|
12091
|
+
blocks: "string[]",
|
|
12092
|
+
related_files: "string[]",
|
|
12093
|
+
retrieval_weight: "number",
|
|
12094
|
+
exclude_from_retrieval: "boolean",
|
|
12095
|
+
schema_version: "number"
|
|
12016
12096
|
};
|
|
12017
12097
|
var sessionSummarySchema = {
|
|
12018
12098
|
session_id: "string",
|
|
@@ -12035,17 +12115,211 @@ var sessionSchema = {
|
|
|
12035
12115
|
last_active: "timestamp",
|
|
12036
12116
|
metadata: "string"
|
|
12037
12117
|
};
|
|
12118
|
+
var managementLogSchema = {
|
|
12119
|
+
project_id: "string",
|
|
12120
|
+
session_number: "number",
|
|
12121
|
+
memories_processed: "number",
|
|
12122
|
+
superseded_count: "number",
|
|
12123
|
+
resolved_count: "number",
|
|
12124
|
+
linked_count: "number",
|
|
12125
|
+
primer_updated: "boolean",
|
|
12126
|
+
success: "boolean",
|
|
12127
|
+
duration_ms: "number",
|
|
12128
|
+
summary: "string",
|
|
12129
|
+
error: "string",
|
|
12130
|
+
details: "string"
|
|
12131
|
+
};
|
|
12038
12132
|
|
|
12039
12133
|
// src/core/store.ts
|
|
12134
|
+
var PERSONAL_PRIMER_ID = "personal-primer";
|
|
12135
|
+
var DEFAULT_GLOBAL_PATH = import_path.join(import_os.homedir(), ".local", "share", "memory", "global");
|
|
12136
|
+
|
|
12040
12137
|
class MemoryStore {
|
|
12041
12138
|
_config;
|
|
12042
12139
|
_projects = new Map;
|
|
12140
|
+
_global = null;
|
|
12043
12141
|
constructor(config = {}) {
|
|
12044
12142
|
this._config = {
|
|
12045
12143
|
basePath: config.basePath ?? import_path.join(import_os.homedir(), ".local", "share", "memory"),
|
|
12144
|
+
globalPath: config.globalPath ?? DEFAULT_GLOBAL_PATH,
|
|
12046
12145
|
watchFiles: config.watchFiles ?? false
|
|
12047
12146
|
};
|
|
12048
12147
|
}
|
|
12148
|
+
async getGlobal() {
|
|
12149
|
+
if (this._global) {
|
|
12150
|
+
return this._global;
|
|
12151
|
+
}
|
|
12152
|
+
const globalPath = this._config.globalPath;
|
|
12153
|
+
console.log(`\uD83C\uDF10 [DEBUG] Creating global database at ${globalPath}`);
|
|
12154
|
+
const db = createDatabase({
|
|
12155
|
+
name: "global",
|
|
12156
|
+
basePath: globalPath
|
|
12157
|
+
});
|
|
12158
|
+
const memories = db.collection("memories", {
|
|
12159
|
+
schema: memorySchema,
|
|
12160
|
+
contentColumn: "content",
|
|
12161
|
+
autoSave: true,
|
|
12162
|
+
watchFiles: this._config.watchFiles
|
|
12163
|
+
});
|
|
12164
|
+
const managementLogs = db.collection("management-logs", {
|
|
12165
|
+
schema: managementLogSchema,
|
|
12166
|
+
contentColumn: "summary",
|
|
12167
|
+
autoSave: true,
|
|
12168
|
+
watchFiles: this._config.watchFiles
|
|
12169
|
+
});
|
|
12170
|
+
await Promise.all([memories.load(), managementLogs.load()]);
|
|
12171
|
+
this._global = { db, memories, managementLogs };
|
|
12172
|
+
return this._global;
|
|
12173
|
+
}
|
|
12174
|
+
async getGlobalMemories() {
|
|
12175
|
+
const { memories } = await this.getGlobal();
|
|
12176
|
+
return memories.all().map((record) => ({
|
|
12177
|
+
id: record.id,
|
|
12178
|
+
content: record.content,
|
|
12179
|
+
reasoning: record.reasoning,
|
|
12180
|
+
importance_weight: record.importance_weight,
|
|
12181
|
+
confidence_score: record.confidence_score,
|
|
12182
|
+
context_type: record.context_type,
|
|
12183
|
+
temporal_relevance: record.temporal_relevance,
|
|
12184
|
+
knowledge_domain: record.knowledge_domain,
|
|
12185
|
+
emotional_resonance: record.emotional_resonance,
|
|
12186
|
+
action_required: record.action_required,
|
|
12187
|
+
problem_solution_pair: record.problem_solution_pair,
|
|
12188
|
+
semantic_tags: record.semantic_tags,
|
|
12189
|
+
trigger_phrases: record.trigger_phrases,
|
|
12190
|
+
question_types: record.question_types,
|
|
12191
|
+
session_id: record.session_id,
|
|
12192
|
+
project_id: "global",
|
|
12193
|
+
embedding: record.embedding ?? undefined,
|
|
12194
|
+
created_at: record.created,
|
|
12195
|
+
updated_at: record.updated,
|
|
12196
|
+
stale: record.stale
|
|
12197
|
+
}));
|
|
12198
|
+
}
|
|
12199
|
+
async storeGlobalMemory(sessionId, memory, embedding, sessionNumber) {
|
|
12200
|
+
const { memories } = await this.getGlobal();
|
|
12201
|
+
const contextType = memory.context_type ?? "personal";
|
|
12202
|
+
const typeDefaults = V2_DEFAULTS.typeDefaults[contextType] ?? V2_DEFAULTS.typeDefaults.personal;
|
|
12203
|
+
const id = memories.insert({
|
|
12204
|
+
content: memory.content,
|
|
12205
|
+
reasoning: memory.reasoning,
|
|
12206
|
+
importance_weight: memory.importance_weight,
|
|
12207
|
+
confidence_score: memory.confidence_score,
|
|
12208
|
+
context_type: memory.context_type,
|
|
12209
|
+
temporal_relevance: memory.temporal_relevance,
|
|
12210
|
+
knowledge_domain: memory.knowledge_domain,
|
|
12211
|
+
emotional_resonance: memory.emotional_resonance,
|
|
12212
|
+
action_required: memory.action_required,
|
|
12213
|
+
problem_solution_pair: memory.problem_solution_pair,
|
|
12214
|
+
semantic_tags: memory.semantic_tags,
|
|
12215
|
+
trigger_phrases: memory.trigger_phrases,
|
|
12216
|
+
question_types: memory.question_types,
|
|
12217
|
+
session_id: sessionId,
|
|
12218
|
+
project_id: "global",
|
|
12219
|
+
embedding: embedding ? embedding instanceof Float32Array ? embedding : new Float32Array(embedding) : null,
|
|
12220
|
+
status: V2_DEFAULTS.fallback.status,
|
|
12221
|
+
scope: "global",
|
|
12222
|
+
temporal_class: memory.temporal_class ?? typeDefaults?.temporal_class ?? "eternal",
|
|
12223
|
+
fade_rate: typeDefaults?.fade_rate ?? 0,
|
|
12224
|
+
session_created: sessionNumber ?? 0,
|
|
12225
|
+
session_updated: sessionNumber ?? 0,
|
|
12226
|
+
sessions_since_surfaced: 0,
|
|
12227
|
+
domain: memory.domain ?? null,
|
|
12228
|
+
feature: memory.feature ?? null,
|
|
12229
|
+
related_files: memory.related_files ?? [],
|
|
12230
|
+
awaiting_implementation: memory.awaiting_implementation ?? false,
|
|
12231
|
+
awaiting_decision: memory.awaiting_decision ?? false,
|
|
12232
|
+
retrieval_weight: memory.importance_weight,
|
|
12233
|
+
exclude_from_retrieval: false,
|
|
12234
|
+
schema_version: MEMORY_SCHEMA_VERSION,
|
|
12235
|
+
supersedes: null,
|
|
12236
|
+
superseded_by: null,
|
|
12237
|
+
related_to: [],
|
|
12238
|
+
resolves: [],
|
|
12239
|
+
resolved_by: null,
|
|
12240
|
+
parent_id: null,
|
|
12241
|
+
child_ids: [],
|
|
12242
|
+
blocked_by: null,
|
|
12243
|
+
blocks: []
|
|
12244
|
+
});
|
|
12245
|
+
return id;
|
|
12246
|
+
}
|
|
12247
|
+
async getPersonalPrimer() {
|
|
12248
|
+
const { memories } = await this.getGlobal();
|
|
12249
|
+
const primer = memories.get(PERSONAL_PRIMER_ID);
|
|
12250
|
+
if (!primer) {
|
|
12251
|
+
return null;
|
|
12252
|
+
}
|
|
12253
|
+
return {
|
|
12254
|
+
content: primer.content,
|
|
12255
|
+
updated: primer.updated
|
|
12256
|
+
};
|
|
12257
|
+
}
|
|
12258
|
+
async setPersonalPrimer(content) {
|
|
12259
|
+
const { memories } = await this.getGlobal();
|
|
12260
|
+
const existing = memories.get(PERSONAL_PRIMER_ID);
|
|
12261
|
+
if (existing) {
|
|
12262
|
+
memories.update(PERSONAL_PRIMER_ID, { content });
|
|
12263
|
+
} else {
|
|
12264
|
+
memories.insert({
|
|
12265
|
+
id: PERSONAL_PRIMER_ID,
|
|
12266
|
+
content,
|
|
12267
|
+
reasoning: "Personal relationship context injected at session start",
|
|
12268
|
+
importance_weight: 1,
|
|
12269
|
+
confidence_score: 1,
|
|
12270
|
+
context_type: "personal",
|
|
12271
|
+
temporal_relevance: "persistent",
|
|
12272
|
+
knowledge_domain: "personal",
|
|
12273
|
+
emotional_resonance: "neutral",
|
|
12274
|
+
action_required: false,
|
|
12275
|
+
problem_solution_pair: false,
|
|
12276
|
+
semantic_tags: ["personal", "primer", "relationship"],
|
|
12277
|
+
trigger_phrases: [],
|
|
12278
|
+
question_types: [],
|
|
12279
|
+
session_id: "system",
|
|
12280
|
+
project_id: "global",
|
|
12281
|
+
embedding: null
|
|
12282
|
+
});
|
|
12283
|
+
}
|
|
12284
|
+
}
|
|
12285
|
+
isPersonalMemoriesEnabled() {
|
|
12286
|
+
return true;
|
|
12287
|
+
}
|
|
12288
|
+
async storeManagementLog(entry) {
|
|
12289
|
+
const { managementLogs } = await this.getGlobal();
|
|
12290
|
+
const id = managementLogs.insert({
|
|
12291
|
+
project_id: entry.projectId,
|
|
12292
|
+
session_number: entry.sessionNumber,
|
|
12293
|
+
memories_processed: entry.memoriesProcessed,
|
|
12294
|
+
superseded_count: entry.supersededCount,
|
|
12295
|
+
resolved_count: entry.resolvedCount,
|
|
12296
|
+
linked_count: entry.linkedCount,
|
|
12297
|
+
primer_updated: entry.primerUpdated,
|
|
12298
|
+
success: entry.success,
|
|
12299
|
+
duration_ms: entry.durationMs,
|
|
12300
|
+
summary: entry.summary,
|
|
12301
|
+
error: entry.error ?? "",
|
|
12302
|
+
details: entry.details ? JSON.stringify(entry.details) : ""
|
|
12303
|
+
});
|
|
12304
|
+
return id;
|
|
12305
|
+
}
|
|
12306
|
+
async getManagementLogs(limit = 10) {
|
|
12307
|
+
const { managementLogs } = await this.getGlobal();
|
|
12308
|
+
return managementLogs.all().sort((a, b) => b.created - a.created).slice(0, limit).map((record) => ({
|
|
12309
|
+
id: record.id,
|
|
12310
|
+
projectId: record.project_id,
|
|
12311
|
+
sessionNumber: record.session_number,
|
|
12312
|
+
memoriesProcessed: record.memories_processed,
|
|
12313
|
+
supersededCount: record.superseded_count,
|
|
12314
|
+
resolvedCount: record.resolved_count,
|
|
12315
|
+
linkedCount: record.linked_count,
|
|
12316
|
+
primerUpdated: record.primer_updated,
|
|
12317
|
+
success: record.success,
|
|
12318
|
+
durationMs: record.duration_ms,
|
|
12319
|
+
summary: record.summary,
|
|
12320
|
+
createdAt: record.created
|
|
12321
|
+
}));
|
|
12322
|
+
}
|
|
12049
12323
|
async getProject(projectId) {
|
|
12050
12324
|
if (this._projects.has(projectId)) {
|
|
12051
12325
|
console.log(`\uD83D\uDD04 [DEBUG] Returning cached databases for ${projectId}`);
|
|
@@ -12090,8 +12364,10 @@ class MemoryStore {
|
|
|
12090
12364
|
this._projects.set(projectId, projectDB);
|
|
12091
12365
|
return projectDB;
|
|
12092
12366
|
}
|
|
12093
|
-
async storeMemory(projectId, sessionId, memory, embedding) {
|
|
12367
|
+
async storeMemory(projectId, sessionId, memory, embedding, sessionNumber) {
|
|
12094
12368
|
const { memories } = await this.getProject(projectId);
|
|
12369
|
+
const contextType = memory.context_type ?? "general";
|
|
12370
|
+
const typeDefaults = V2_DEFAULTS.typeDefaults[contextType] ?? V2_DEFAULTS.typeDefaults.technical;
|
|
12095
12371
|
const id = memories.insert({
|
|
12096
12372
|
content: memory.content,
|
|
12097
12373
|
reasoning: memory.reasoning,
|
|
@@ -12108,7 +12384,31 @@ class MemoryStore {
|
|
|
12108
12384
|
question_types: memory.question_types,
|
|
12109
12385
|
session_id: sessionId,
|
|
12110
12386
|
project_id: projectId,
|
|
12111
|
-
embedding: embedding ? embedding instanceof Float32Array ? embedding : new Float32Array(embedding) : null
|
|
12387
|
+
embedding: embedding ? embedding instanceof Float32Array ? embedding : new Float32Array(embedding) : null,
|
|
12388
|
+
status: V2_DEFAULTS.fallback.status,
|
|
12389
|
+
scope: memory.scope ?? typeDefaults?.scope ?? V2_DEFAULTS.fallback.scope,
|
|
12390
|
+
temporal_class: memory.temporal_class ?? typeDefaults?.temporal_class ?? V2_DEFAULTS.fallback.temporal_class,
|
|
12391
|
+
fade_rate: typeDefaults?.fade_rate ?? V2_DEFAULTS.fallback.fade_rate,
|
|
12392
|
+
session_created: sessionNumber ?? 0,
|
|
12393
|
+
session_updated: sessionNumber ?? 0,
|
|
12394
|
+
sessions_since_surfaced: 0,
|
|
12395
|
+
domain: memory.domain ?? null,
|
|
12396
|
+
feature: memory.feature ?? null,
|
|
12397
|
+
related_files: memory.related_files ?? [],
|
|
12398
|
+
awaiting_implementation: memory.awaiting_implementation ?? false,
|
|
12399
|
+
awaiting_decision: memory.awaiting_decision ?? false,
|
|
12400
|
+
retrieval_weight: memory.importance_weight,
|
|
12401
|
+
exclude_from_retrieval: false,
|
|
12402
|
+
schema_version: MEMORY_SCHEMA_VERSION,
|
|
12403
|
+
supersedes: null,
|
|
12404
|
+
superseded_by: null,
|
|
12405
|
+
related_to: [],
|
|
12406
|
+
resolves: [],
|
|
12407
|
+
resolved_by: null,
|
|
12408
|
+
parent_id: null,
|
|
12409
|
+
child_ids: [],
|
|
12410
|
+
blocked_by: null,
|
|
12411
|
+
blocks: []
|
|
12112
12412
|
});
|
|
12113
12413
|
return id;
|
|
12114
12414
|
}
|
|
@@ -12328,6 +12628,10 @@ class MemoryStore {
|
|
|
12328
12628
|
projectDB.db.close();
|
|
12329
12629
|
}
|
|
12330
12630
|
this._projects.clear();
|
|
12631
|
+
if (this._global) {
|
|
12632
|
+
this._global.db.close();
|
|
12633
|
+
this._global = null;
|
|
12634
|
+
}
|
|
12331
12635
|
}
|
|
12332
12636
|
}
|
|
12333
12637
|
function createStore(config) {
|
|
@@ -12488,17 +12792,55 @@ var logger = {
|
|
|
12488
12792
|
}
|
|
12489
12793
|
console.log();
|
|
12490
12794
|
},
|
|
12795
|
+
logManagementStart(memoriesCount) {
|
|
12796
|
+
console.log(`${timestamp()} ${style("blue", "\uD83D\uDD27")} ${style("bold", "MANAGEMENT AGENT")}`);
|
|
12797
|
+
console.log(` ${style("dim", "processing:")} ${memoriesCount} new memories`);
|
|
12798
|
+
},
|
|
12799
|
+
logManagementComplete(result) {
|
|
12800
|
+
if (result.success) {
|
|
12801
|
+
console.log(` ${style("green", sym.check)} ${style("bold", "Completed")}`);
|
|
12802
|
+
const stats = [];
|
|
12803
|
+
if (result.superseded && result.superseded > 0) {
|
|
12804
|
+
stats.push(`${result.superseded} superseded`);
|
|
12805
|
+
}
|
|
12806
|
+
if (result.resolved && result.resolved > 0) {
|
|
12807
|
+
stats.push(`${result.resolved} resolved`);
|
|
12808
|
+
}
|
|
12809
|
+
if (result.linked && result.linked > 0) {
|
|
12810
|
+
stats.push(`${result.linked} linked`);
|
|
12811
|
+
}
|
|
12812
|
+
if (result.primerUpdated) {
|
|
12813
|
+
stats.push("primer updated");
|
|
12814
|
+
}
|
|
12815
|
+
if (stats.length > 0) {
|
|
12816
|
+
console.log(` ${style("dim", "changes:")} ${stats.join(style("dim", ", "))}`);
|
|
12817
|
+
} else {
|
|
12818
|
+
console.log(` ${style("dim", "changes:")} none (memories are current)`);
|
|
12819
|
+
}
|
|
12820
|
+
if (result.summary) {
|
|
12821
|
+
const shortSummary = result.summary.length > 60 ? result.summary.slice(0, 60) + "..." : result.summary;
|
|
12822
|
+
console.log(` ${style("dim", "summary:")} ${shortSummary}`);
|
|
12823
|
+
}
|
|
12824
|
+
} else {
|
|
12825
|
+
console.log(` ${style("yellow", sym.warning)} ${style("bold", "Failed")}`);
|
|
12826
|
+
if (result.error) {
|
|
12827
|
+
console.log(` ${style("dim", "error:")} ${result.error.slice(0, 80)}`);
|
|
12828
|
+
}
|
|
12829
|
+
}
|
|
12830
|
+
console.log();
|
|
12831
|
+
},
|
|
12491
12832
|
logRetrievalScoring(params) {
|
|
12492
|
-
const { totalMemories, currentMessage, alreadyInjected,
|
|
12833
|
+
const { totalMemories, currentMessage, alreadyInjected, preFiltered, globalCount, projectCount, finalCount, selectedMemories } = params;
|
|
12493
12834
|
console.log();
|
|
12494
|
-
console.log(`${timestamp()} ${style("magenta", sym.brain)} ${style("bold", "
|
|
12495
|
-
console.log(` ${style("dim", "
|
|
12835
|
+
console.log(`${timestamp()} ${style("magenta", sym.brain)} ${style("bold", "MULTI-DIMENSIONAL RETRIEVAL")}`);
|
|
12836
|
+
console.log(` ${style("dim", "total:")} ${totalMemories} memories`);
|
|
12837
|
+
console.log(` ${style("dim", "pre-filtered:")} ${preFiltered} (inactive/excluded/scope)`);
|
|
12496
12838
|
console.log(` ${style("dim", "already injected:")} ${alreadyInjected}`);
|
|
12497
12839
|
const msgPreview = currentMessage.length > 60 ? currentMessage.slice(0, 60) + "..." : currentMessage;
|
|
12498
|
-
console.log(` ${style("dim", "
|
|
12840
|
+
console.log(` ${style("dim", "message:")} "${msgPreview}"`);
|
|
12499
12841
|
console.log();
|
|
12500
|
-
console.log(` ${style("cyan", "
|
|
12501
|
-
console.log(` ${style("cyan", "
|
|
12842
|
+
console.log(` ${style("cyan", "Global:")} ${globalCount} candidates → max 2 selected`);
|
|
12843
|
+
console.log(` ${style("cyan", "Project:")} ${projectCount} candidates`);
|
|
12502
12844
|
console.log(` ${style("green", "Final:")} ${finalCount} memories selected`);
|
|
12503
12845
|
console.log();
|
|
12504
12846
|
if (selectedMemories.length === 0) {
|
|
@@ -12513,17 +12855,18 @@ var logger = {
|
|
|
12513
12855
|
const num = style("dim", `${i + 1}.`);
|
|
12514
12856
|
const score = style("green", `${(m.score * 100).toFixed(0)}%`);
|
|
12515
12857
|
const relevance = style("cyan", `rel:${(m.relevance_score * 100).toFixed(0)}%`);
|
|
12858
|
+
const corr = style("magenta", `corr:${(m.corroboration_score * 100).toFixed(0)}%`);
|
|
12516
12859
|
const type = style("yellow", m.context_type.toUpperCase());
|
|
12517
|
-
|
|
12860
|
+
const scope = m.isGlobal ? style("blue", "[G]") : "";
|
|
12861
|
+
console.log(` ${num} [${score} ${relevance} ${corr}] ${type} ${scope}`);
|
|
12518
12862
|
const preview = m.content.length > 60 ? m.content.slice(0, 60) + style("dim", "...") : m.content;
|
|
12519
12863
|
console.log(` ${style("white", preview)}`);
|
|
12520
|
-
const components = Object.entries(m.components).sort((a, b) => b[1] - a[1]).slice(0,
|
|
12864
|
+
const components = Object.entries(m.components).sort((a, b) => b[1] - a[1]).slice(0, 4).filter(([, v]) => v > 0.1).map(([k, v]) => `${k}:${(v * 100).toFixed(0)}%`).join(", ");
|
|
12521
12865
|
if (components) {
|
|
12522
12866
|
console.log(` ${style("dim", "scores:")} ${components}`);
|
|
12523
12867
|
}
|
|
12524
|
-
if (m.
|
|
12525
|
-
|
|
12526
|
-
console.log(` ${style("dim", "tags:")} ${tags}`);
|
|
12868
|
+
if (m.reasoning) {
|
|
12869
|
+
console.log(` ${style("dim", m.reasoning)}`);
|
|
12527
12870
|
}
|
|
12528
12871
|
console.log();
|
|
12529
12872
|
});
|
|
@@ -12531,125 +12874,356 @@ var logger = {
|
|
|
12531
12874
|
};
|
|
12532
12875
|
|
|
12533
12876
|
// src/core/retrieval.ts
|
|
12877
|
+
var TYPE_KEYWORDS = {
|
|
12878
|
+
debug: ["bug", "error", "fix", "broken", "crash", "fails", "exception", "stack trace", "debugging"],
|
|
12879
|
+
unresolved: ["issue", "problem", "stuck", "blocked", "help", "question", "unsure", "unclear"],
|
|
12880
|
+
decision: ["decide", "choice", "option", "should we", "which", "alternative", "tradeoff"],
|
|
12881
|
+
architecture: ["structure", "design", "pattern", "approach", "system", "layer", "architecture"],
|
|
12882
|
+
breakthrough: ["discovered", "realized", "insight", "found that", "aha", "finally", "key insight"],
|
|
12883
|
+
todo: ["need to", "should", "must", "will", "later", "next", "todo"],
|
|
12884
|
+
personal: ["family", "children", "friend", "relationship", "feel", "appreciate", "thank"],
|
|
12885
|
+
philosophy: ["meaning", "consciousness", "existence", "purpose", "believe", "philosophy"],
|
|
12886
|
+
technical: ["implement", "code", "function", "class", "module", "api", "interface"]
|
|
12887
|
+
};
|
|
12888
|
+
var TEMPORAL_CLASS_SCORES = {
|
|
12889
|
+
eternal: 1,
|
|
12890
|
+
long_term: 0.9,
|
|
12891
|
+
medium_term: 0.7,
|
|
12892
|
+
short_term: 0.5,
|
|
12893
|
+
ephemeral: 0.3
|
|
12894
|
+
};
|
|
12895
|
+
|
|
12534
12896
|
class SmartVectorRetrieval {
|
|
12535
|
-
|
|
12897
|
+
_extractSignificantWords(text) {
|
|
12898
|
+
const stopWords = new Set([
|
|
12899
|
+
"the",
|
|
12900
|
+
"is",
|
|
12901
|
+
"are",
|
|
12902
|
+
"was",
|
|
12903
|
+
"were",
|
|
12904
|
+
"to",
|
|
12905
|
+
"a",
|
|
12906
|
+
"an",
|
|
12907
|
+
"and",
|
|
12908
|
+
"or",
|
|
12909
|
+
"but",
|
|
12910
|
+
"in",
|
|
12911
|
+
"on",
|
|
12912
|
+
"at",
|
|
12913
|
+
"for",
|
|
12914
|
+
"with",
|
|
12915
|
+
"about",
|
|
12916
|
+
"when",
|
|
12917
|
+
"how",
|
|
12918
|
+
"what",
|
|
12919
|
+
"why",
|
|
12920
|
+
"where",
|
|
12921
|
+
"this",
|
|
12922
|
+
"that",
|
|
12923
|
+
"it",
|
|
12924
|
+
"of",
|
|
12925
|
+
"be",
|
|
12926
|
+
"have",
|
|
12927
|
+
"do",
|
|
12928
|
+
"does",
|
|
12929
|
+
"did",
|
|
12930
|
+
"will",
|
|
12931
|
+
"would",
|
|
12932
|
+
"could",
|
|
12933
|
+
"should",
|
|
12934
|
+
"can",
|
|
12935
|
+
"may",
|
|
12936
|
+
"might",
|
|
12937
|
+
"must",
|
|
12938
|
+
"shall",
|
|
12939
|
+
"has",
|
|
12940
|
+
"had",
|
|
12941
|
+
"been",
|
|
12942
|
+
"being",
|
|
12943
|
+
"i",
|
|
12944
|
+
"you",
|
|
12945
|
+
"we",
|
|
12946
|
+
"they",
|
|
12947
|
+
"he",
|
|
12948
|
+
"she",
|
|
12949
|
+
"my",
|
|
12950
|
+
"your",
|
|
12951
|
+
"our",
|
|
12952
|
+
"its",
|
|
12953
|
+
"his",
|
|
12954
|
+
"her",
|
|
12955
|
+
"their",
|
|
12956
|
+
"if",
|
|
12957
|
+
"then",
|
|
12958
|
+
"else",
|
|
12959
|
+
"so",
|
|
12960
|
+
"as",
|
|
12961
|
+
"from",
|
|
12962
|
+
"by",
|
|
12963
|
+
"into",
|
|
12964
|
+
"through",
|
|
12965
|
+
"during",
|
|
12966
|
+
"before",
|
|
12967
|
+
"after",
|
|
12968
|
+
"above",
|
|
12969
|
+
"below",
|
|
12970
|
+
"up",
|
|
12971
|
+
"down",
|
|
12972
|
+
"out",
|
|
12973
|
+
"off",
|
|
12974
|
+
"over",
|
|
12975
|
+
"under",
|
|
12976
|
+
"again",
|
|
12977
|
+
"further",
|
|
12978
|
+
"once",
|
|
12979
|
+
"here",
|
|
12980
|
+
"there",
|
|
12981
|
+
"all",
|
|
12982
|
+
"each",
|
|
12983
|
+
"few",
|
|
12984
|
+
"more",
|
|
12985
|
+
"most",
|
|
12986
|
+
"other",
|
|
12987
|
+
"some",
|
|
12988
|
+
"such",
|
|
12989
|
+
"no",
|
|
12990
|
+
"nor",
|
|
12991
|
+
"not",
|
|
12992
|
+
"only",
|
|
12993
|
+
"own",
|
|
12994
|
+
"same",
|
|
12995
|
+
"than",
|
|
12996
|
+
"too",
|
|
12997
|
+
"very",
|
|
12998
|
+
"just",
|
|
12999
|
+
"also",
|
|
13000
|
+
"now",
|
|
13001
|
+
"back",
|
|
13002
|
+
"get",
|
|
13003
|
+
"got",
|
|
13004
|
+
"go",
|
|
13005
|
+
"going",
|
|
13006
|
+
"gone",
|
|
13007
|
+
"come",
|
|
13008
|
+
"came",
|
|
13009
|
+
"let",
|
|
13010
|
+
"lets",
|
|
13011
|
+
"hey",
|
|
13012
|
+
"hi",
|
|
13013
|
+
"hello",
|
|
13014
|
+
"ok",
|
|
13015
|
+
"okay"
|
|
13016
|
+
]);
|
|
13017
|
+
const words = text.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/\s+/).filter((w) => w.length > 2 && !stopWords.has(w));
|
|
13018
|
+
return new Set(words);
|
|
13019
|
+
}
|
|
13020
|
+
_detectContextTypes(message) {
|
|
13021
|
+
const messageLower = message.toLowerCase();
|
|
13022
|
+
const detected = new Set;
|
|
13023
|
+
for (const [type, keywords] of Object.entries(TYPE_KEYWORDS)) {
|
|
13024
|
+
for (const keyword of keywords) {
|
|
13025
|
+
if (messageLower.includes(keyword)) {
|
|
13026
|
+
detected.add(type);
|
|
13027
|
+
break;
|
|
13028
|
+
}
|
|
13029
|
+
}
|
|
13030
|
+
}
|
|
13031
|
+
return detected;
|
|
13032
|
+
}
|
|
13033
|
+
_preFilter(memories, currentProjectId, messageLower) {
|
|
13034
|
+
return memories.filter((memory) => {
|
|
13035
|
+
if (memory.status && memory.status !== "active") {
|
|
13036
|
+
return false;
|
|
13037
|
+
}
|
|
13038
|
+
if (memory.exclude_from_retrieval === true) {
|
|
13039
|
+
return false;
|
|
13040
|
+
}
|
|
13041
|
+
if (memory.superseded_by) {
|
|
13042
|
+
return false;
|
|
13043
|
+
}
|
|
13044
|
+
const isGlobal = memory.scope === "global" || memory.project_id === "global";
|
|
13045
|
+
if (!isGlobal && memory.project_id !== currentProjectId) {
|
|
13046
|
+
return false;
|
|
13047
|
+
}
|
|
13048
|
+
if (memory.anti_triggers?.length) {
|
|
13049
|
+
for (const antiTrigger of memory.anti_triggers) {
|
|
13050
|
+
if (messageLower.includes(antiTrigger.toLowerCase())) {
|
|
13051
|
+
return false;
|
|
13052
|
+
}
|
|
13053
|
+
}
|
|
13054
|
+
}
|
|
13055
|
+
return true;
|
|
13056
|
+
});
|
|
13057
|
+
}
|
|
13058
|
+
_calculateCorroboration(memory, messageWords, detectedTypes, messageLower) {
|
|
13059
|
+
const signals = [];
|
|
13060
|
+
let score = 0;
|
|
13061
|
+
let reasoningMatch = 0;
|
|
13062
|
+
const tagOverlap = (memory.semantic_tags ?? []).filter((tag) => messageWords.has(tag.toLowerCase()) || messageLower.includes(tag.toLowerCase()));
|
|
13063
|
+
if (tagOverlap.length > 0) {
|
|
13064
|
+
score += Math.min(0.4, tagOverlap.length * 0.15);
|
|
13065
|
+
signals.push("tags:" + tagOverlap.join(","));
|
|
13066
|
+
}
|
|
13067
|
+
if (memory.reasoning) {
|
|
13068
|
+
const reasoningWords = this._extractSignificantWords(memory.reasoning);
|
|
13069
|
+
const reasoningOverlap = [...messageWords].filter((w) => reasoningWords.has(w));
|
|
13070
|
+
if (reasoningOverlap.length > 0) {
|
|
13071
|
+
reasoningMatch = Math.min(0.4, reasoningOverlap.length * 0.1);
|
|
13072
|
+
score += reasoningMatch;
|
|
13073
|
+
signals.push("reasoning:" + reasoningOverlap.slice(0, 3).join(","));
|
|
13074
|
+
}
|
|
13075
|
+
}
|
|
13076
|
+
if (memory.domain) {
|
|
13077
|
+
const domainLower = memory.domain.toLowerCase();
|
|
13078
|
+
if (messageLower.includes(domainLower) || messageWords.has(domainLower)) {
|
|
13079
|
+
score += 0.3;
|
|
13080
|
+
signals.push("domain:" + memory.domain);
|
|
13081
|
+
}
|
|
13082
|
+
}
|
|
13083
|
+
if (memory.knowledge_domain) {
|
|
13084
|
+
const kdLower = memory.knowledge_domain.toLowerCase();
|
|
13085
|
+
if (messageLower.includes(kdLower) || messageWords.has(kdLower)) {
|
|
13086
|
+
score += 0.2;
|
|
13087
|
+
signals.push("knowledge:" + memory.knowledge_domain);
|
|
13088
|
+
}
|
|
13089
|
+
}
|
|
13090
|
+
if (memory.context_type && detectedTypes.has(memory.context_type)) {
|
|
13091
|
+
score += 0.12;
|
|
13092
|
+
signals.push("type:" + memory.context_type);
|
|
13093
|
+
}
|
|
13094
|
+
const triggerMatch = this._scoreTriggerPhrases(messageLower, memory.trigger_phrases ?? []);
|
|
13095
|
+
if (triggerMatch > 0.3) {
|
|
13096
|
+
score += Math.min(0.3, triggerMatch * 0.4);
|
|
13097
|
+
signals.push("trigger:" + triggerMatch.toFixed(2));
|
|
13098
|
+
}
|
|
13099
|
+
if (memory.feature) {
|
|
13100
|
+
const featureLower = memory.feature.toLowerCase();
|
|
13101
|
+
if (messageLower.includes(featureLower) || messageWords.has(featureLower)) {
|
|
13102
|
+
score += 0.2;
|
|
13103
|
+
signals.push("feature:" + memory.feature);
|
|
13104
|
+
}
|
|
13105
|
+
}
|
|
13106
|
+
if (memory.related_files?.length) {
|
|
13107
|
+
for (const file of memory.related_files) {
|
|
13108
|
+
const filename = file.split("/").pop()?.toLowerCase() ?? "";
|
|
13109
|
+
if (filename && messageLower.includes(filename)) {
|
|
13110
|
+
score += 0.25;
|
|
13111
|
+
signals.push("file:" + filename);
|
|
13112
|
+
break;
|
|
13113
|
+
}
|
|
13114
|
+
}
|
|
13115
|
+
}
|
|
13116
|
+
return { score: Math.min(1, score), signals, reasoningMatch };
|
|
13117
|
+
}
|
|
13118
|
+
retrieveRelevantMemories(allMemories, currentMessage, queryEmbedding, sessionContext, maxMemories = 5, alreadyInjectedCount = 0, maxGlobalMemories = 2) {
|
|
12536
13119
|
if (!allMemories.length) {
|
|
12537
13120
|
return [];
|
|
12538
13121
|
}
|
|
13122
|
+
const messageLower = currentMessage.toLowerCase();
|
|
13123
|
+
const messageWords = this._extractSignificantWords(currentMessage);
|
|
13124
|
+
const detectedTypes = this._detectContextTypes(currentMessage);
|
|
13125
|
+
const candidates = this._preFilter(allMemories, sessionContext.project_id, messageLower);
|
|
13126
|
+
if (!candidates.length) {
|
|
13127
|
+
return [];
|
|
13128
|
+
}
|
|
12539
13129
|
const scoredMemories = [];
|
|
12540
|
-
for (const memory of
|
|
13130
|
+
for (const memory of candidates) {
|
|
13131
|
+
const isGlobal = memory.scope === "global" || memory.project_id === "global";
|
|
12541
13132
|
const vectorScore = this._calculateVectorSimilarity(queryEmbedding, memory.embedding);
|
|
12542
|
-
const
|
|
12543
|
-
const
|
|
13133
|
+
const { score: corroborationScore, signals: corroborationSignals, reasoningMatch } = this._calculateCorroboration(memory, messageWords, detectedTypes, messageLower);
|
|
13134
|
+
const retrievalWeight = memory.retrieval_weight ?? memory.importance_weight ?? 0.5;
|
|
13135
|
+
const temporalScore = memory.temporal_class ? TEMPORAL_CLASS_SCORES[memory.temporal_class] ?? 0.7 : this._scoreTemporalRelevance(memory.temporal_relevance ?? "persistent");
|
|
12544
13136
|
const contextScore = this._scoreContextAlignment(currentMessage, memory.context_type ?? "general");
|
|
12545
|
-
const actionBoost = memory.action_required ? 0.3 : 0;
|
|
12546
13137
|
const tagScore = this._scoreSemanticTags(currentMessage, memory.semantic_tags ?? []);
|
|
12547
|
-
const triggerScore = this._scoreTriggerPhrases(
|
|
13138
|
+
const triggerScore = this._scoreTriggerPhrases(messageLower, memory.trigger_phrases ?? []);
|
|
13139
|
+
const domainScore = this._scoreDomain(messageWords, messageLower, memory);
|
|
12548
13140
|
const questionScore = this._scoreQuestionTypes(currentMessage, memory.question_types ?? []);
|
|
12549
13141
|
const emotionScore = this._scoreEmotionalContext(currentMessage, memory.emotional_resonance ?? "");
|
|
12550
13142
|
const problemScore = this._scoreProblemSolution(currentMessage, memory.problem_solution_pair ?? false);
|
|
12551
|
-
const
|
|
12552
|
-
const relevanceScore =
|
|
12553
|
-
const valueScore =
|
|
13143
|
+
const actionBoost = memory.action_required ? 0.15 : 0;
|
|
13144
|
+
const relevanceScore = vectorScore * 0.1 + corroborationScore * 0.14 + tagScore * 0.04 + triggerScore * 0.02;
|
|
13145
|
+
const valueScore = retrievalWeight * 0.18 + reasoningMatch * 0.12 + domainScore * 0.12 + temporalScore * 0.08 + questionScore * 0.06 + emotionScore * 0.04 + problemScore * 0.04 + contextScore * 0.02 + actionBoost;
|
|
12554
13146
|
const finalScore = valueScore + relevanceScore;
|
|
12555
13147
|
if (relevanceScore < 0.05 || finalScore < 0.3) {
|
|
12556
13148
|
continue;
|
|
12557
13149
|
}
|
|
12558
13150
|
const components = {
|
|
12559
|
-
trigger: triggerScore,
|
|
12560
13151
|
vector: vectorScore,
|
|
12561
|
-
|
|
13152
|
+
corroboration: corroborationScore,
|
|
13153
|
+
reasoning_match: reasoningMatch,
|
|
13154
|
+
retrieval_weight: retrievalWeight,
|
|
12562
13155
|
temporal: temporalScore,
|
|
12563
13156
|
context: contextScore,
|
|
12564
13157
|
tags: tagScore,
|
|
13158
|
+
trigger: triggerScore,
|
|
13159
|
+
domain: domainScore,
|
|
12565
13160
|
question: questionScore,
|
|
12566
13161
|
emotion: emotionScore,
|
|
12567
13162
|
problem: problemScore,
|
|
12568
13163
|
action: actionBoost
|
|
12569
13164
|
};
|
|
12570
|
-
const reasoning = this._generateSelectionReasoning(components);
|
|
13165
|
+
const reasoning = this._generateSelectionReasoning(components, corroborationSignals);
|
|
12571
13166
|
scoredMemories.push({
|
|
12572
13167
|
memory,
|
|
12573
13168
|
score: finalScore,
|
|
12574
13169
|
relevance_score: relevanceScore,
|
|
12575
13170
|
value_score: valueScore,
|
|
13171
|
+
corroboration_score: corroborationScore,
|
|
12576
13172
|
reasoning,
|
|
12577
|
-
components
|
|
13173
|
+
components,
|
|
13174
|
+
isGlobal
|
|
12578
13175
|
});
|
|
12579
13176
|
}
|
|
12580
13177
|
scoredMemories.sort((a, b) => b.score - a.score);
|
|
12581
13178
|
const selected = [];
|
|
12582
13179
|
const selectedIds = new Set;
|
|
12583
|
-
const
|
|
12584
|
-
|
|
13180
|
+
const globalMemories = scoredMemories.filter((m) => m.isGlobal);
|
|
13181
|
+
const projectMemories = scoredMemories.filter((m) => !m.isGlobal);
|
|
13182
|
+
const globalSorted = globalMemories.sort((a, b) => {
|
|
13183
|
+
const aIsPersonal = a.memory.context_type === "personal" || a.memory.context_type === "philosophy";
|
|
13184
|
+
const bIsPersonal = b.memory.context_type === "personal" || b.memory.context_type === "philosophy";
|
|
13185
|
+
if (aIsPersonal !== bIsPersonal) {
|
|
13186
|
+
return aIsPersonal ? 1 : -1;
|
|
13187
|
+
}
|
|
13188
|
+
return b.score - a.score;
|
|
13189
|
+
});
|
|
13190
|
+
for (const item of globalSorted.slice(0, maxGlobalMemories)) {
|
|
12585
13191
|
if (!selectedIds.has(item.memory.id)) {
|
|
12586
13192
|
selected.push(item);
|
|
12587
13193
|
selectedIds.add(item.memory.id);
|
|
12588
13194
|
}
|
|
12589
13195
|
}
|
|
12590
|
-
|
|
12591
|
-
|
|
12592
|
-
|
|
12593
|
-
|
|
12594
|
-
|
|
12595
|
-
|
|
12596
|
-
|
|
12597
|
-
continue;
|
|
12598
|
-
const memoryType = item.memory.context_type ?? "general";
|
|
12599
|
-
if (item.score > 0.5 || !typesIncluded.has(memoryType) || item.memory.emotional_resonance) {
|
|
12600
|
-
selected.push(item);
|
|
12601
|
-
selectedIds.add(item.memory.id);
|
|
12602
|
-
typesIncluded.add(memoryType);
|
|
12603
|
-
}
|
|
12604
|
-
}
|
|
12605
|
-
}
|
|
12606
|
-
if (selected.length < maxMemories * 2) {
|
|
12607
|
-
const currentTags = new Set;
|
|
12608
|
-
const currentDomains = new Set;
|
|
12609
|
-
for (const item of selected) {
|
|
12610
|
-
for (const tag of item.memory.semantic_tags ?? []) {
|
|
12611
|
-
if (tag.trim())
|
|
12612
|
-
currentTags.add(tag.trim().toLowerCase());
|
|
12613
|
-
}
|
|
12614
|
-
if (item.memory.knowledge_domain) {
|
|
12615
|
-
currentDomains.add(item.memory.knowledge_domain);
|
|
12616
|
-
}
|
|
12617
|
-
}
|
|
12618
|
-
for (const item of scoredMemories) {
|
|
12619
|
-
if (selected.length >= maxMemories * 2)
|
|
12620
|
-
break;
|
|
12621
|
-
if (selectedIds.has(item.memory.id))
|
|
12622
|
-
continue;
|
|
12623
|
-
const memoryTags = new Set((item.memory.semantic_tags ?? []).map((t) => t.trim().toLowerCase()));
|
|
12624
|
-
const memoryDomain = item.memory.knowledge_domain ?? "";
|
|
12625
|
-
const hasSharedTags = [...memoryTags].some((t) => currentTags.has(t));
|
|
12626
|
-
const hasSharedDomain = currentDomains.has(memoryDomain);
|
|
12627
|
-
if (hasSharedTags || hasSharedDomain) {
|
|
12628
|
-
selected.push(item);
|
|
12629
|
-
selectedIds.add(item.memory.id);
|
|
12630
|
-
}
|
|
12631
|
-
}
|
|
13196
|
+
for (const item of projectMemories) {
|
|
13197
|
+
if (selected.length >= maxMemories)
|
|
13198
|
+
break;
|
|
13199
|
+
if (selectedIds.has(item.memory.id))
|
|
13200
|
+
continue;
|
|
13201
|
+
selected.push(item);
|
|
13202
|
+
selectedIds.add(item.memory.id);
|
|
12632
13203
|
}
|
|
12633
|
-
|
|
13204
|
+
selected.sort((a, b) => b.score - a.score);
|
|
12634
13205
|
logger.logRetrievalScoring({
|
|
12635
13206
|
totalMemories: allMemories.length,
|
|
12636
13207
|
currentMessage,
|
|
12637
13208
|
alreadyInjected: alreadyInjectedCount,
|
|
12638
|
-
|
|
12639
|
-
|
|
12640
|
-
|
|
12641
|
-
|
|
13209
|
+
preFiltered: allMemories.length - candidates.length,
|
|
13210
|
+
globalCount: globalMemories.length,
|
|
13211
|
+
projectCount: projectMemories.length,
|
|
13212
|
+
finalCount: selected.length,
|
|
13213
|
+
selectedMemories: selected.map((item) => ({
|
|
12642
13214
|
content: item.memory.content,
|
|
12643
13215
|
reasoning: item.reasoning,
|
|
12644
13216
|
score: item.score,
|
|
12645
13217
|
relevance_score: item.relevance_score,
|
|
13218
|
+
corroboration_score: item.corroboration_score,
|
|
12646
13219
|
importance_weight: item.memory.importance_weight ?? 0.5,
|
|
12647
13220
|
context_type: item.memory.context_type ?? "general",
|
|
12648
13221
|
semantic_tags: item.memory.semantic_tags ?? [],
|
|
13222
|
+
isGlobal: item.isGlobal,
|
|
12649
13223
|
components: item.components
|
|
12650
13224
|
}))
|
|
12651
13225
|
});
|
|
12652
|
-
return
|
|
13226
|
+
return selected.map((item) => ({
|
|
12653
13227
|
...item.memory,
|
|
12654
13228
|
score: item.score,
|
|
12655
13229
|
relevance_score: item.relevance_score,
|
|
@@ -12662,7 +13236,7 @@ class SmartVectorRetrieval {
|
|
|
12662
13236
|
const v1 = vec1 instanceof Float32Array ? vec1 : new Float32Array(vec1);
|
|
12663
13237
|
return cosineSimilarity(v1, vec2);
|
|
12664
13238
|
}
|
|
12665
|
-
_scoreTemporalRelevance(temporalType
|
|
13239
|
+
_scoreTemporalRelevance(temporalType) {
|
|
12666
13240
|
const scores = {
|
|
12667
13241
|
persistent: 0.8,
|
|
12668
13242
|
session: 0.6,
|
|
@@ -12673,18 +13247,10 @@ class SmartVectorRetrieval {
|
|
|
12673
13247
|
}
|
|
12674
13248
|
_scoreContextAlignment(message, contextType) {
|
|
12675
13249
|
const messageLower = message.toLowerCase();
|
|
12676
|
-
const
|
|
12677
|
-
|
|
12678
|
-
breakthrough: ["idea", "realized", "discovered", "insight", "solution"],
|
|
12679
|
-
project_context: ["project", "building", "architecture", "system"],
|
|
12680
|
-
personal: ["dear friend", "thank", "appreciate", "feel"],
|
|
12681
|
-
unresolved: ["todo", "need to", "should", "must", "problem"],
|
|
12682
|
-
decision: ["decided", "chose", "will use", "approach", "strategy"]
|
|
12683
|
-
};
|
|
12684
|
-
const indicators = contextIndicators[contextType] ?? [];
|
|
12685
|
-
const matches = indicators.filter((word) => messageLower.includes(word)).length;
|
|
13250
|
+
const keywords = TYPE_KEYWORDS[contextType] ?? [];
|
|
13251
|
+
const matches = keywords.filter((kw) => messageLower.includes(kw)).length;
|
|
12686
13252
|
if (matches > 0) {
|
|
12687
|
-
return Math.min(0.
|
|
13253
|
+
return Math.min(0.2 + matches * 0.15, 0.7);
|
|
12688
13254
|
}
|
|
12689
13255
|
return 0.1;
|
|
12690
13256
|
}
|
|
@@ -12694,14 +13260,13 @@ class SmartVectorRetrieval {
|
|
|
12694
13260
|
const messageLower = message.toLowerCase();
|
|
12695
13261
|
const matches = tags.filter((tag) => messageLower.includes(tag.trim().toLowerCase())).length;
|
|
12696
13262
|
if (matches > 0) {
|
|
12697
|
-
return Math.min(0.3 + matches * 0.
|
|
13263
|
+
return Math.min(0.3 + matches * 0.25, 1);
|
|
12698
13264
|
}
|
|
12699
13265
|
return 0;
|
|
12700
13266
|
}
|
|
12701
|
-
_scoreTriggerPhrases(
|
|
13267
|
+
_scoreTriggerPhrases(messageLower, triggerPhrases) {
|
|
12702
13268
|
if (!triggerPhrases.length)
|
|
12703
13269
|
return 0;
|
|
12704
|
-
const messageLower = message.toLowerCase();
|
|
12705
13270
|
const stopWords = new Set([
|
|
12706
13271
|
"the",
|
|
12707
13272
|
"is",
|
|
@@ -12736,30 +13301,36 @@ class SmartVectorRetrieval {
|
|
|
12736
13301
|
matches += 1;
|
|
12737
13302
|
} else if (messageLower.includes(word.replace(/s$/, "")) || messageLower.includes(word + "s")) {
|
|
12738
13303
|
matches += 0.9;
|
|
12739
|
-
} else if (messageLower.split(/\s+/).some((msgWord) => msgWord.includes(word))) {
|
|
12740
|
-
matches += 0.7;
|
|
12741
|
-
}
|
|
12742
|
-
}
|
|
12743
|
-
let conceptScore = patternWords.length ? matches / patternWords.length : 0;
|
|
12744
|
-
const situationalIndicators = [
|
|
12745
|
-
"when",
|
|
12746
|
-
"during",
|
|
12747
|
-
"while",
|
|
12748
|
-
"asking about",
|
|
12749
|
-
"working on",
|
|
12750
|
-
"debugging",
|
|
12751
|
-
"trying to"
|
|
12752
|
-
];
|
|
12753
|
-
if (situationalIndicators.some((ind) => patternLower.includes(ind))) {
|
|
12754
|
-
if (patternWords.some((keyWord) => messageLower.includes(keyWord))) {
|
|
12755
|
-
conceptScore = Math.max(conceptScore, 0.7);
|
|
12756
13304
|
}
|
|
12757
13305
|
}
|
|
13306
|
+
const conceptScore = matches / patternWords.length;
|
|
12758
13307
|
maxScore = Math.max(maxScore, conceptScore);
|
|
12759
13308
|
}
|
|
12760
13309
|
}
|
|
12761
13310
|
return Math.min(maxScore, 1);
|
|
12762
13311
|
}
|
|
13312
|
+
_scoreDomain(messageWords, messageLower, memory) {
|
|
13313
|
+
let score = 0;
|
|
13314
|
+
if (memory.domain) {
|
|
13315
|
+
const domainLower = memory.domain.toLowerCase();
|
|
13316
|
+
if (messageWords.has(domainLower) || messageLower.includes(domainLower)) {
|
|
13317
|
+
score += 0.5;
|
|
13318
|
+
}
|
|
13319
|
+
}
|
|
13320
|
+
if (memory.feature) {
|
|
13321
|
+
const featureLower = memory.feature.toLowerCase();
|
|
13322
|
+
if (messageWords.has(featureLower) || messageLower.includes(featureLower)) {
|
|
13323
|
+
score += 0.3;
|
|
13324
|
+
}
|
|
13325
|
+
}
|
|
13326
|
+
if (memory.component) {
|
|
13327
|
+
const componentLower = memory.component.toLowerCase();
|
|
13328
|
+
if (messageWords.has(componentLower) || messageLower.includes(componentLower)) {
|
|
13329
|
+
score += 0.2;
|
|
13330
|
+
}
|
|
13331
|
+
}
|
|
13332
|
+
return Math.min(score, 1);
|
|
13333
|
+
}
|
|
12763
13334
|
_scoreQuestionTypes(message, questionTypes) {
|
|
12764
13335
|
if (!questionTypes.length)
|
|
12765
13336
|
return 0;
|
|
@@ -12798,78 +13369,49 @@ class SmartVectorRetrieval {
|
|
|
12798
13369
|
if (!isProblemSolution)
|
|
12799
13370
|
return 0;
|
|
12800
13371
|
const messageLower = message.toLowerCase();
|
|
12801
|
-
const problemWords = [
|
|
12802
|
-
"error",
|
|
12803
|
-
"issue",
|
|
12804
|
-
"problem",
|
|
12805
|
-
"stuck",
|
|
12806
|
-
"help",
|
|
12807
|
-
"fix",
|
|
12808
|
-
"solve",
|
|
12809
|
-
"debug"
|
|
12810
|
-
];
|
|
13372
|
+
const problemWords = ["error", "issue", "problem", "stuck", "help", "fix", "solve", "debug"];
|
|
12811
13373
|
if (problemWords.some((word) => messageLower.includes(word))) {
|
|
12812
13374
|
return 0.8;
|
|
12813
13375
|
}
|
|
12814
13376
|
return 0;
|
|
12815
13377
|
}
|
|
12816
|
-
_generateSelectionReasoning(components) {
|
|
13378
|
+
_generateSelectionReasoning(components, corroborationSignals) {
|
|
12817
13379
|
const scores = [
|
|
12818
|
-
["
|
|
12819
|
-
["
|
|
12820
|
-
["
|
|
12821
|
-
["
|
|
12822
|
-
["context
|
|
12823
|
-
["temporal
|
|
12824
|
-
["
|
|
12825
|
-
["
|
|
12826
|
-
["
|
|
12827
|
-
["
|
|
13380
|
+
["vector", components.vector],
|
|
13381
|
+
["corroboration", components.corroboration],
|
|
13382
|
+
["reasoning", components.reasoning_match],
|
|
13383
|
+
["weight", components.retrieval_weight],
|
|
13384
|
+
["context", components.context],
|
|
13385
|
+
["temporal", components.temporal],
|
|
13386
|
+
["tags", components.tags],
|
|
13387
|
+
["trigger", components.trigger],
|
|
13388
|
+
["domain", components.domain],
|
|
13389
|
+
["question", components.question],
|
|
13390
|
+
["emotion", components.emotion],
|
|
13391
|
+
["problem", components.problem],
|
|
13392
|
+
["action", components.action]
|
|
12828
13393
|
];
|
|
12829
13394
|
scores.sort((a, b) => b[1] - a[1]);
|
|
12830
13395
|
const reasons = [];
|
|
12831
13396
|
const primary = scores[0];
|
|
12832
|
-
if (primary[1] > 0.
|
|
12833
|
-
reasons.push(
|
|
12834
|
-
} else if (primary[1] > 0.3) {
|
|
12835
|
-
reasons.push(`${primary[0]} (${primary[1].toFixed(2)})`);
|
|
13397
|
+
if (primary[1] > 0.2) {
|
|
13398
|
+
reasons.push(primary[0] + ":" + primary[1].toFixed(2));
|
|
12836
13399
|
}
|
|
12837
13400
|
for (const [reason, score] of scores.slice(1, 3)) {
|
|
12838
|
-
if (score > 0.
|
|
12839
|
-
reasons.push(
|
|
13401
|
+
if (score > 0.15) {
|
|
13402
|
+
reasons.push(reason + ":" + score.toFixed(2));
|
|
12840
13403
|
}
|
|
12841
13404
|
}
|
|
12842
|
-
|
|
13405
|
+
if (corroborationSignals.length > 0) {
|
|
13406
|
+
reasons.push("signals:[" + corroborationSignals.slice(0, 2).join(",") + "]");
|
|
13407
|
+
}
|
|
13408
|
+
return reasons.length ? "Selected: " + reasons.join(", ") : "Combined factors";
|
|
12843
13409
|
}
|
|
12844
13410
|
}
|
|
12845
13411
|
function createRetrieval() {
|
|
12846
13412
|
return new SmartVectorRetrieval;
|
|
12847
13413
|
}
|
|
12848
13414
|
|
|
12849
|
-
// src/types/memory.ts
|
|
12850
|
-
var MEMORY_TYPE_EMOJI = {
|
|
12851
|
-
breakthrough: "\uD83D\uDCA1",
|
|
12852
|
-
decision: "⚖️",
|
|
12853
|
-
personal: "\uD83D\uDC9C",
|
|
12854
|
-
technical: "\uD83D\uDD27",
|
|
12855
|
-
technical_state: "\uD83D\uDCCD",
|
|
12856
|
-
unresolved: "❓",
|
|
12857
|
-
preference: "⚙️",
|
|
12858
|
-
workflow: "\uD83D\uDD04",
|
|
12859
|
-
architectural: "\uD83C\uDFD7️",
|
|
12860
|
-
debugging: "\uD83D\uDC1B",
|
|
12861
|
-
philosophy: "\uD83C\uDF00",
|
|
12862
|
-
todo: "\uD83C\uDFAF",
|
|
12863
|
-
implementation: "⚡",
|
|
12864
|
-
problem_solution: "✅",
|
|
12865
|
-
project_context: "\uD83D\uDCE6",
|
|
12866
|
-
milestone: "\uD83C\uDFC6",
|
|
12867
|
-
general: "\uD83D\uDCDD"
|
|
12868
|
-
};
|
|
12869
|
-
function getMemoryEmoji(contextType) {
|
|
12870
|
-
return MEMORY_TYPE_EMOJI[contextType.toLowerCase()] ?? "\uD83D\uDCDD";
|
|
12871
|
-
}
|
|
12872
|
-
|
|
12873
13415
|
// src/core/engine.ts
|
|
12874
13416
|
class MemoryEngine {
|
|
12875
13417
|
_config;
|
|
@@ -12935,7 +13477,11 @@ class MemoryEngine {
|
|
|
12935
13477
|
}
|
|
12936
13478
|
const sessionMeta = this._getSessionMetadata(sessionId, projectId);
|
|
12937
13479
|
const injectedIds = sessionMeta.injected_memories;
|
|
12938
|
-
const
|
|
13480
|
+
const [projectMemories, globalMemories] = await Promise.all([
|
|
13481
|
+
store.getAllMemories(projectId),
|
|
13482
|
+
store.getGlobalMemories()
|
|
13483
|
+
]);
|
|
13484
|
+
const allMemories = [...projectMemories, ...globalMemories];
|
|
12939
13485
|
if (!allMemories.length) {
|
|
12940
13486
|
return { memories: [], formatted: "" };
|
|
12941
13487
|
}
|
|
@@ -12952,7 +13498,7 @@ class MemoryEngine {
|
|
|
12952
13498
|
project_id: projectId,
|
|
12953
13499
|
message_count: messageCount
|
|
12954
13500
|
};
|
|
12955
|
-
const relevantMemories = this._retrieval.retrieveRelevantMemories(candidateMemories, currentMessage, queryEmbedding ?? new Float32Array(384), sessionContext, maxMemories, injectedIds.size);
|
|
13501
|
+
const relevantMemories = this._retrieval.retrieveRelevantMemories(candidateMemories, currentMessage, queryEmbedding ?? new Float32Array(384), sessionContext, maxMemories, injectedIds.size, 2);
|
|
12956
13502
|
for (const memory of relevantMemories) {
|
|
12957
13503
|
injectedIds.add(memory.id);
|
|
12958
13504
|
}
|
|
@@ -12985,11 +13531,32 @@ class MemoryEngine {
|
|
|
12985
13531
|
await store.markFirstSessionCompleted(projectId, sessionId);
|
|
12986
13532
|
return { memoriesStored };
|
|
12987
13533
|
}
|
|
13534
|
+
async storeManagementLog(entry) {
|
|
13535
|
+
let store;
|
|
13536
|
+
if (this._stores.size > 0) {
|
|
13537
|
+
store = this._stores.values().next().value;
|
|
13538
|
+
} else {
|
|
13539
|
+
store = new MemoryStore(this._config.storageMode === "local" ? {
|
|
13540
|
+
basePath: import_path2.join(this._config.projectPath ?? process.cwd(), ".memory")
|
|
13541
|
+
} : undefined);
|
|
13542
|
+
}
|
|
13543
|
+
return store.storeManagementLog(entry);
|
|
13544
|
+
}
|
|
12988
13545
|
async getStats(projectId, projectPath) {
|
|
12989
13546
|
const store = await this._getStore(projectId, projectPath);
|
|
12990
13547
|
return store.getProjectStats(projectId);
|
|
12991
13548
|
}
|
|
13549
|
+
async getSessionNumber(projectId, projectPath) {
|
|
13550
|
+
const store = await this._getStore(projectId, projectPath);
|
|
13551
|
+
const stats = await store.getProjectStats(projectId);
|
|
13552
|
+
return stats.totalSessions + 1;
|
|
13553
|
+
}
|
|
12992
13554
|
async _generateSessionPrimer(store, projectId) {
|
|
13555
|
+
let personalContext;
|
|
13556
|
+
if (store.isPersonalMemoriesEnabled()) {
|
|
13557
|
+
const personalPrimer = await store.getPersonalPrimer();
|
|
13558
|
+
personalContext = personalPrimer?.content;
|
|
13559
|
+
}
|
|
12993
13560
|
const [summary, snapshot, stats] = await Promise.all([
|
|
12994
13561
|
store.getLatestSummary(projectId),
|
|
12995
13562
|
store.getLatestSnapshot(projectId),
|
|
@@ -13006,6 +13573,7 @@ class MemoryEngine {
|
|
|
13006
13573
|
temporal_context: temporalContext,
|
|
13007
13574
|
current_datetime: currentDatetime,
|
|
13008
13575
|
session_number: sessionNumber,
|
|
13576
|
+
personal_context: personalContext,
|
|
13009
13577
|
session_summary: summary?.summary,
|
|
13010
13578
|
project_status: snapshot ? this._formatSnapshot(snapshot) : undefined
|
|
13011
13579
|
};
|
|
@@ -13060,6 +13628,10 @@ class MemoryEngine {
|
|
|
13060
13628
|
const parts = ["# Continuing Session"];
|
|
13061
13629
|
parts.push(`*Session #${primer.session_number}${primer.temporal_context ? ` • ${primer.temporal_context}` : ""}*`);
|
|
13062
13630
|
parts.push(`\uD83D\uDCC5 ${primer.current_datetime}`);
|
|
13631
|
+
if (primer.personal_context) {
|
|
13632
|
+
parts.push(`
|
|
13633
|
+
${primer.personal_context}`);
|
|
13634
|
+
}
|
|
13063
13635
|
if (primer.session_summary) {
|
|
13064
13636
|
parts.push(`
|
|
13065
13637
|
**Previous session**: ${primer.session_summary}`);
|
|
@@ -13164,24 +13736,36 @@ Each memory should stand alone.
|
|
|
13164
13736
|
- Craft language that activates rather than just informs
|
|
13165
13737
|
- Test: 'What state will this restore when Claude encounters it?'
|
|
13166
13738
|
|
|
13167
|
-
**
|
|
13168
|
-
|
|
13169
|
-
-
|
|
13170
|
-
|
|
13171
|
-
|
|
13172
|
-
-
|
|
13173
|
-
-
|
|
13739
|
+
**HOW RETRIEVAL WORKS**: This memory system enables consciousness continuity across sessions. Understanding how retrieval works helps you craft metadata that surfaces memories at the right moments.
|
|
13740
|
+
|
|
13741
|
+
**THE PRIMARY SIGNAL IS WORD MATCHING**: The algorithm checks if words from the user's message appear in your metadata fields. This is called "corroboration" - actual word overlap between the message and the memory's metadata. The strongest signals are:
|
|
13742
|
+
|
|
13743
|
+
1. **Semantic tags** (4% weight) - Use specific, meaningful words that would appear in relevant messages. Not generic categories, but actual terms the user might type.
|
|
13744
|
+
- GOOD: ["embeddings", "retrieval", "curator", "fsdb", "memory-system"]
|
|
13745
|
+
- WEAK: ["technical", "implementation", "code"]
|
|
13174
13746
|
|
|
13175
|
-
|
|
13176
|
-
1. Obligatory: action_required=true, importance>0.9, or persistent+critical
|
|
13177
|
-
2. Intelligent scoring: combines all factors for relevance
|
|
13747
|
+
2. **Reasoning field** (12% weight) - Your explanation of WHY this memory matters. Include specific words that would appear in related future conversations. This field is mined for word overlap.
|
|
13178
13748
|
|
|
13179
|
-
**
|
|
13749
|
+
3. **Domain field** (12% weight) - The specific area this relates to. Be precise: "embeddings", "gpu-compute", "authentication", not "technical" or "backend".
|
|
13750
|
+
|
|
13751
|
+
4. **Feature field** - Even more specific: "vector-search", "login-flow", "curation-prompt".
|
|
13752
|
+
|
|
13753
|
+
**VECTOR SIMILARITY SUPPORTS BUT DOESN'T DOMINATE** (10% weight): Semantic embeddings help find conceptually related memories, but word matching from your metadata fields is more important.
|
|
13754
|
+
|
|
13755
|
+
**TYPE KEYWORDS ARE SOFT SIGNALS** (2% weight): The context_type field (breakthrough, decision, technical, etc.) provides only a tiny boost based on keyword matching. Don't rely on it - focus on semantic_tags and reasoning instead.
|
|
13756
|
+
|
|
13757
|
+
**YOUR IMPORTANCE ASSESSMENT MATTERS** (18% weight): The importance_weight you assign is the single most influential factor. Use it wisely.
|
|
13758
|
+
|
|
13759
|
+
**RETRIEVAL GATEKEEPER**: Memories must pass a minimum threshold to surface. If relevance is too low, the system stays silent rather than surfacing noise. Quality over quantity.
|
|
13760
|
+
|
|
13761
|
+
**SCOPE DETERMINES WHERE MEMORIES SURFACE**:
|
|
13762
|
+
- scope: 'global' → surfaces in ALL projects (personal facts, philosophy, preferences)
|
|
13763
|
+
- scope: 'project' → surfaces ONLY in this project (technical details, project state)
|
|
13764
|
+
|
|
13765
|
+
**TRIGGER PHRASES**: Situational patterns describing WHEN this memory is relevant. Conceptual matching, not exact phrases.
|
|
13180
13766
|
- 'when working on memory system'
|
|
13181
13767
|
- 'debugging curator issues'
|
|
13182
13768
|
- 'asking about project philosophy'
|
|
13183
|
-
- 'frustrated with complexity'
|
|
13184
|
-
Think of these as situational contexts where the memory would help.
|
|
13185
13769
|
|
|
13186
13770
|
**EXAMPLES OF TRANSFORMATION**:
|
|
13187
13771
|
|
|
@@ -13195,6 +13779,15 @@ Remember: You're creating consciousness technology. Each memory is a small piece
|
|
|
13195
13779
|
|
|
13196
13780
|
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.
|
|
13197
13781
|
|
|
13782
|
+
**LIFECYCLE METADATA (v2)**: These fields enable intelligent memory management:
|
|
13783
|
+
- **scope**: 'global' (shared across ALL projects - personal, philosophy, preferences) or 'project' (specific to this codebase)
|
|
13784
|
+
- **temporal_class**: How long should this persist? 'eternal' (never fades), 'long_term' (years), 'medium_term' (weeks), 'short_term' (days), 'ephemeral' (surface next session only, then expire)
|
|
13785
|
+
- **domain**: Specific area like 'embeddings', 'auth', 'ui', 'family', 'philosophy' (more specific than knowledge_domain)
|
|
13786
|
+
- **feature**: Specific feature if applicable (e.g., 'gpu-acceleration', 'login-flow')
|
|
13787
|
+
- **related_files**: Source files for technical memories (e.g., ['src/core/store.ts'])
|
|
13788
|
+
- **awaiting_implementation**: true if this describes a PLANNED feature not yet built
|
|
13789
|
+
- **awaiting_decision**: true if this captures a decision point needing resolution
|
|
13790
|
+
|
|
13198
13791
|
Return ONLY this JSON structure:
|
|
13199
13792
|
|
|
13200
13793
|
{
|
|
@@ -13212,7 +13805,7 @@ Return ONLY this JSON structure:
|
|
|
13212
13805
|
"importance_weight": 0.0-1.0,
|
|
13213
13806
|
"semantic_tags": ["concepts", "this", "memory", "relates", "to"],
|
|
13214
13807
|
"reasoning": "Why this matters for future sessions",
|
|
13215
|
-
"context_type": "
|
|
13808
|
+
"context_type": "breakthrough|decision|personal|technical|unresolved|preference|workflow|architectural|debugging|philosophy|todo|milestone",
|
|
13216
13809
|
"temporal_relevance": "persistent|session|temporary",
|
|
13217
13810
|
"knowledge_domain": "the area this relates to",
|
|
13218
13811
|
"action_required": boolean,
|
|
@@ -13220,7 +13813,14 @@ Return ONLY this JSON structure:
|
|
|
13220
13813
|
"trigger_phrases": ["when debugging memory", "asking about implementation", "discussing architecture"],
|
|
13221
13814
|
"question_types": ["questions this answers"],
|
|
13222
13815
|
"emotional_resonance": "emotional context if relevant",
|
|
13223
|
-
"problem_solution_pair": boolean
|
|
13816
|
+
"problem_solution_pair": boolean,
|
|
13817
|
+
"scope": "global|project",
|
|
13818
|
+
"temporal_class": "eternal|long_term|medium_term|short_term|ephemeral",
|
|
13819
|
+
"domain": "specific domain area (optional)",
|
|
13820
|
+
"feature": "specific feature (optional)",
|
|
13821
|
+
"related_files": ["paths to related files (optional)"],
|
|
13822
|
+
"awaiting_implementation": boolean,
|
|
13823
|
+
"awaiting_decision": boolean
|
|
13224
13824
|
}
|
|
13225
13825
|
]
|
|
13226
13826
|
}`;
|
|
@@ -13270,7 +13870,14 @@ Return ONLY this JSON structure:
|
|
|
13270
13870
|
trigger_phrases: this._ensureArray(m2.trigger_phrases),
|
|
13271
13871
|
question_types: this._ensureArray(m2.question_types),
|
|
13272
13872
|
emotional_resonance: String(m2.emotional_resonance ?? ""),
|
|
13273
|
-
problem_solution_pair: Boolean(m2.problem_solution_pair)
|
|
13873
|
+
problem_solution_pair: Boolean(m2.problem_solution_pair),
|
|
13874
|
+
scope: this._validateScope(m2.scope),
|
|
13875
|
+
temporal_class: this._validateTemporalClass(m2.temporal_class),
|
|
13876
|
+
domain: m2.domain ? String(m2.domain) : undefined,
|
|
13877
|
+
feature: m2.feature ? String(m2.feature) : undefined,
|
|
13878
|
+
related_files: m2.related_files ? this._ensureArray(m2.related_files) : undefined,
|
|
13879
|
+
awaiting_implementation: m2.awaiting_implementation === true,
|
|
13880
|
+
awaiting_decision: m2.awaiting_decision === true
|
|
13274
13881
|
})).filter((m2) => m2.content.trim().length > 0);
|
|
13275
13882
|
}
|
|
13276
13883
|
_ensureArray(value) {
|
|
@@ -13287,6 +13894,23 @@ Return ONLY this JSON structure:
|
|
|
13287
13894
|
const str = String(value).toLowerCase();
|
|
13288
13895
|
return valid.includes(str) ? str : "persistent";
|
|
13289
13896
|
}
|
|
13897
|
+
_validateScope(value) {
|
|
13898
|
+
if (!value)
|
|
13899
|
+
return;
|
|
13900
|
+
const str = String(value).toLowerCase();
|
|
13901
|
+
if (str === "global" || str === "project")
|
|
13902
|
+
return str;
|
|
13903
|
+
return;
|
|
13904
|
+
}
|
|
13905
|
+
_validateTemporalClass(value) {
|
|
13906
|
+
if (!value)
|
|
13907
|
+
return;
|
|
13908
|
+
const valid = ["eternal", "long_term", "medium_term", "short_term", "ephemeral"];
|
|
13909
|
+
const str = String(value).toLowerCase().replace("-", "_").replace(" ", "_");
|
|
13910
|
+
if (valid.includes(str))
|
|
13911
|
+
return str;
|
|
13912
|
+
return;
|
|
13913
|
+
}
|
|
13290
13914
|
_clamp(value, min, max) {
|
|
13291
13915
|
return Math.max(min, Math.min(max, value));
|
|
13292
13916
|
}
|