@rlabs-inc/memory 0.3.5 → 0.3.6

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.
@@ -19731,7 +19731,60 @@ function createDatabase(options = {}) {
19731
19731
  import { homedir } from "os";
19732
19732
  import { join } from "path";
19733
19733
 
19734
+ // src/types/memory.ts
19735
+ var V2_DEFAULTS = {
19736
+ typeDefaults: {
19737
+ personal: { scope: "global", temporal_class: "eternal", fade_rate: 0 },
19738
+ philosophy: { scope: "global", temporal_class: "eternal", fade_rate: 0 },
19739
+ preference: { scope: "global", temporal_class: "long_term", fade_rate: 0.01 },
19740
+ breakthrough: { scope: "project", temporal_class: "eternal", fade_rate: 0 },
19741
+ decision: { scope: "project", temporal_class: "long_term", fade_rate: 0 },
19742
+ milestone: { scope: "project", temporal_class: "eternal", fade_rate: 0 },
19743
+ technical: { scope: "project", temporal_class: "medium_term", fade_rate: 0.03 },
19744
+ architectural: { scope: "project", temporal_class: "long_term", fade_rate: 0.01 },
19745
+ debugging: { scope: "project", temporal_class: "medium_term", fade_rate: 0.03 },
19746
+ unresolved: { scope: "project", temporal_class: "medium_term", fade_rate: 0.05 },
19747
+ todo: { scope: "project", temporal_class: "short_term", fade_rate: 0.1 },
19748
+ technical_state: { scope: "project", temporal_class: "short_term", fade_rate: 0.1 },
19749
+ workflow: { scope: "project", temporal_class: "long_term", fade_rate: 0.02 },
19750
+ project_context: { scope: "project", temporal_class: "medium_term", fade_rate: 0.03 }
19751
+ },
19752
+ fallback: {
19753
+ status: "active",
19754
+ scope: "project",
19755
+ temporal_class: "medium_term",
19756
+ fade_rate: 0.03,
19757
+ sessions_since_surfaced: 0,
19758
+ awaiting_implementation: false,
19759
+ awaiting_decision: false,
19760
+ exclude_from_retrieval: false
19761
+ }
19762
+ };
19763
+ var MEMORY_TYPE_EMOJI = {
19764
+ breakthrough: "\uD83D\uDCA1",
19765
+ decision: "⚖️",
19766
+ personal: "\uD83D\uDC9C",
19767
+ technical: "\uD83D\uDD27",
19768
+ technical_state: "\uD83D\uDCCD",
19769
+ unresolved: "❓",
19770
+ preference: "⚙️",
19771
+ workflow: "\uD83D\uDD04",
19772
+ architectural: "\uD83C\uDFD7️",
19773
+ debugging: "\uD83D\uDC1B",
19774
+ philosophy: "\uD83C\uDF00",
19775
+ todo: "\uD83C\uDFAF",
19776
+ implementation: "⚡",
19777
+ problem_solution: "✅",
19778
+ project_context: "\uD83D\uDCE6",
19779
+ milestone: "\uD83C\uDFC6",
19780
+ general: "\uD83D\uDCDD"
19781
+ };
19782
+ function getMemoryEmoji(contextType) {
19783
+ return MEMORY_TYPE_EMOJI[contextType.toLowerCase()] ?? "\uD83D\uDCDD";
19784
+ }
19785
+
19734
19786
  // src/types/schema.ts
19787
+ var MEMORY_SCHEMA_VERSION = 2;
19735
19788
  var memorySchema = {
19736
19789
  content: "string",
19737
19790
  reasoning: "string",
@@ -19748,7 +19801,34 @@ var memorySchema = {
19748
19801
  question_types: "string[]",
19749
19802
  session_id: "string",
19750
19803
  project_id: "string",
19751
- embedding: "vector:384"
19804
+ embedding: "vector:384",
19805
+ status: "string",
19806
+ scope: "string",
19807
+ session_created: "number",
19808
+ session_updated: "number",
19809
+ last_surfaced: "number",
19810
+ sessions_since_surfaced: "number",
19811
+ temporal_class: "string",
19812
+ fade_rate: "number",
19813
+ expires_after_sessions: "number",
19814
+ domain: "string",
19815
+ feature: "string",
19816
+ component: "string",
19817
+ supersedes: "string",
19818
+ superseded_by: "string",
19819
+ related_to: "string[]",
19820
+ resolves: "string[]",
19821
+ resolved_by: "string",
19822
+ parent_id: "string",
19823
+ child_ids: "string[]",
19824
+ awaiting_implementation: "boolean",
19825
+ awaiting_decision: "boolean",
19826
+ blocked_by: "string",
19827
+ blocks: "string[]",
19828
+ related_files: "string[]",
19829
+ retrieval_weight: "number",
19830
+ exclude_from_retrieval: "boolean",
19831
+ schema_version: "number"
19752
19832
  };
19753
19833
  var sessionSummarySchema = {
19754
19834
  session_id: "string",
@@ -19771,17 +19851,211 @@ var sessionSchema = {
19771
19851
  last_active: "timestamp",
19772
19852
  metadata: "string"
19773
19853
  };
19854
+ var managementLogSchema = {
19855
+ project_id: "string",
19856
+ session_number: "number",
19857
+ memories_processed: "number",
19858
+ superseded_count: "number",
19859
+ resolved_count: "number",
19860
+ linked_count: "number",
19861
+ primer_updated: "boolean",
19862
+ success: "boolean",
19863
+ duration_ms: "number",
19864
+ summary: "string",
19865
+ error: "string",
19866
+ details: "string"
19867
+ };
19774
19868
 
19775
19869
  // src/core/store.ts
19870
+ var PERSONAL_PRIMER_ID = "personal-primer";
19871
+ var DEFAULT_GLOBAL_PATH = join(homedir(), ".local", "share", "memory", "global");
19872
+
19776
19873
  class MemoryStore {
19777
19874
  _config;
19778
19875
  _projects = new Map;
19876
+ _global = null;
19779
19877
  constructor(config = {}) {
19780
19878
  this._config = {
19781
19879
  basePath: config.basePath ?? join(homedir(), ".local", "share", "memory"),
19880
+ globalPath: config.globalPath ?? DEFAULT_GLOBAL_PATH,
19782
19881
  watchFiles: config.watchFiles ?? false
19783
19882
  };
19784
19883
  }
19884
+ async getGlobal() {
19885
+ if (this._global) {
19886
+ return this._global;
19887
+ }
19888
+ const globalPath = this._config.globalPath;
19889
+ console.log(`\uD83C\uDF10 [DEBUG] Creating global database at ${globalPath}`);
19890
+ const db = createDatabase({
19891
+ name: "global",
19892
+ basePath: globalPath
19893
+ });
19894
+ const memories = db.collection("memories", {
19895
+ schema: memorySchema,
19896
+ contentColumn: "content",
19897
+ autoSave: true,
19898
+ watchFiles: this._config.watchFiles
19899
+ });
19900
+ const managementLogs = db.collection("management-logs", {
19901
+ schema: managementLogSchema,
19902
+ contentColumn: "summary",
19903
+ autoSave: true,
19904
+ watchFiles: this._config.watchFiles
19905
+ });
19906
+ await Promise.all([memories.load(), managementLogs.load()]);
19907
+ this._global = { db, memories, managementLogs };
19908
+ return this._global;
19909
+ }
19910
+ async getGlobalMemories() {
19911
+ const { memories } = await this.getGlobal();
19912
+ return memories.all().map((record) => ({
19913
+ id: record.id,
19914
+ content: record.content,
19915
+ reasoning: record.reasoning,
19916
+ importance_weight: record.importance_weight,
19917
+ confidence_score: record.confidence_score,
19918
+ context_type: record.context_type,
19919
+ temporal_relevance: record.temporal_relevance,
19920
+ knowledge_domain: record.knowledge_domain,
19921
+ emotional_resonance: record.emotional_resonance,
19922
+ action_required: record.action_required,
19923
+ problem_solution_pair: record.problem_solution_pair,
19924
+ semantic_tags: record.semantic_tags,
19925
+ trigger_phrases: record.trigger_phrases,
19926
+ question_types: record.question_types,
19927
+ session_id: record.session_id,
19928
+ project_id: "global",
19929
+ embedding: record.embedding ?? undefined,
19930
+ created_at: record.created,
19931
+ updated_at: record.updated,
19932
+ stale: record.stale
19933
+ }));
19934
+ }
19935
+ async storeGlobalMemory(sessionId, memory, embedding, sessionNumber) {
19936
+ const { memories } = await this.getGlobal();
19937
+ const contextType = memory.context_type ?? "personal";
19938
+ const typeDefaults = V2_DEFAULTS.typeDefaults[contextType] ?? V2_DEFAULTS.typeDefaults.personal;
19939
+ const id = memories.insert({
19940
+ content: memory.content,
19941
+ reasoning: memory.reasoning,
19942
+ importance_weight: memory.importance_weight,
19943
+ confidence_score: memory.confidence_score,
19944
+ context_type: memory.context_type,
19945
+ temporal_relevance: memory.temporal_relevance,
19946
+ knowledge_domain: memory.knowledge_domain,
19947
+ emotional_resonance: memory.emotional_resonance,
19948
+ action_required: memory.action_required,
19949
+ problem_solution_pair: memory.problem_solution_pair,
19950
+ semantic_tags: memory.semantic_tags,
19951
+ trigger_phrases: memory.trigger_phrases,
19952
+ question_types: memory.question_types,
19953
+ session_id: sessionId,
19954
+ project_id: "global",
19955
+ embedding: embedding ? embedding instanceof Float32Array ? embedding : new Float32Array(embedding) : null,
19956
+ status: V2_DEFAULTS.fallback.status,
19957
+ scope: "global",
19958
+ temporal_class: memory.temporal_class ?? typeDefaults?.temporal_class ?? "eternal",
19959
+ fade_rate: typeDefaults?.fade_rate ?? 0,
19960
+ session_created: sessionNumber ?? 0,
19961
+ session_updated: sessionNumber ?? 0,
19962
+ sessions_since_surfaced: 0,
19963
+ domain: memory.domain ?? null,
19964
+ feature: memory.feature ?? null,
19965
+ related_files: memory.related_files ?? [],
19966
+ awaiting_implementation: memory.awaiting_implementation ?? false,
19967
+ awaiting_decision: memory.awaiting_decision ?? false,
19968
+ retrieval_weight: memory.importance_weight,
19969
+ exclude_from_retrieval: false,
19970
+ schema_version: MEMORY_SCHEMA_VERSION,
19971
+ supersedes: null,
19972
+ superseded_by: null,
19973
+ related_to: [],
19974
+ resolves: [],
19975
+ resolved_by: null,
19976
+ parent_id: null,
19977
+ child_ids: [],
19978
+ blocked_by: null,
19979
+ blocks: []
19980
+ });
19981
+ return id;
19982
+ }
19983
+ async getPersonalPrimer() {
19984
+ const { memories } = await this.getGlobal();
19985
+ const primer = memories.get(PERSONAL_PRIMER_ID);
19986
+ if (!primer) {
19987
+ return null;
19988
+ }
19989
+ return {
19990
+ content: primer.content,
19991
+ updated: primer.updated
19992
+ };
19993
+ }
19994
+ async setPersonalPrimer(content) {
19995
+ const { memories } = await this.getGlobal();
19996
+ const existing = memories.get(PERSONAL_PRIMER_ID);
19997
+ if (existing) {
19998
+ memories.update(PERSONAL_PRIMER_ID, { content });
19999
+ } else {
20000
+ memories.insert({
20001
+ id: PERSONAL_PRIMER_ID,
20002
+ content,
20003
+ reasoning: "Personal relationship context injected at session start",
20004
+ importance_weight: 1,
20005
+ confidence_score: 1,
20006
+ context_type: "personal",
20007
+ temporal_relevance: "persistent",
20008
+ knowledge_domain: "personal",
20009
+ emotional_resonance: "neutral",
20010
+ action_required: false,
20011
+ problem_solution_pair: false,
20012
+ semantic_tags: ["personal", "primer", "relationship"],
20013
+ trigger_phrases: [],
20014
+ question_types: [],
20015
+ session_id: "system",
20016
+ project_id: "global",
20017
+ embedding: null
20018
+ });
20019
+ }
20020
+ }
20021
+ isPersonalMemoriesEnabled() {
20022
+ return true;
20023
+ }
20024
+ async storeManagementLog(entry) {
20025
+ const { managementLogs } = await this.getGlobal();
20026
+ const id = managementLogs.insert({
20027
+ project_id: entry.projectId,
20028
+ session_number: entry.sessionNumber,
20029
+ memories_processed: entry.memoriesProcessed,
20030
+ superseded_count: entry.supersededCount,
20031
+ resolved_count: entry.resolvedCount,
20032
+ linked_count: entry.linkedCount,
20033
+ primer_updated: entry.primerUpdated,
20034
+ success: entry.success,
20035
+ duration_ms: entry.durationMs,
20036
+ summary: entry.summary,
20037
+ error: entry.error ?? "",
20038
+ details: entry.details ? JSON.stringify(entry.details) : ""
20039
+ });
20040
+ return id;
20041
+ }
20042
+ async getManagementLogs(limit = 10) {
20043
+ const { managementLogs } = await this.getGlobal();
20044
+ return managementLogs.all().sort((a, b) => b.created - a.created).slice(0, limit).map((record) => ({
20045
+ id: record.id,
20046
+ projectId: record.project_id,
20047
+ sessionNumber: record.session_number,
20048
+ memoriesProcessed: record.memories_processed,
20049
+ supersededCount: record.superseded_count,
20050
+ resolvedCount: record.resolved_count,
20051
+ linkedCount: record.linked_count,
20052
+ primerUpdated: record.primer_updated,
20053
+ success: record.success,
20054
+ durationMs: record.duration_ms,
20055
+ summary: record.summary,
20056
+ createdAt: record.created
20057
+ }));
20058
+ }
19785
20059
  async getProject(projectId) {
19786
20060
  if (this._projects.has(projectId)) {
19787
20061
  console.log(`\uD83D\uDD04 [DEBUG] Returning cached databases for ${projectId}`);
@@ -19826,8 +20100,10 @@ class MemoryStore {
19826
20100
  this._projects.set(projectId, projectDB);
19827
20101
  return projectDB;
19828
20102
  }
19829
- async storeMemory(projectId, sessionId, memory, embedding) {
20103
+ async storeMemory(projectId, sessionId, memory, embedding, sessionNumber) {
19830
20104
  const { memories } = await this.getProject(projectId);
20105
+ const contextType = memory.context_type ?? "general";
20106
+ const typeDefaults = V2_DEFAULTS.typeDefaults[contextType] ?? V2_DEFAULTS.typeDefaults.technical;
19831
20107
  const id = memories.insert({
19832
20108
  content: memory.content,
19833
20109
  reasoning: memory.reasoning,
@@ -19844,7 +20120,31 @@ class MemoryStore {
19844
20120
  question_types: memory.question_types,
19845
20121
  session_id: sessionId,
19846
20122
  project_id: projectId,
19847
- embedding: embedding ? embedding instanceof Float32Array ? embedding : new Float32Array(embedding) : null
20123
+ embedding: embedding ? embedding instanceof Float32Array ? embedding : new Float32Array(embedding) : null,
20124
+ status: V2_DEFAULTS.fallback.status,
20125
+ scope: memory.scope ?? typeDefaults?.scope ?? V2_DEFAULTS.fallback.scope,
20126
+ temporal_class: memory.temporal_class ?? typeDefaults?.temporal_class ?? V2_DEFAULTS.fallback.temporal_class,
20127
+ fade_rate: typeDefaults?.fade_rate ?? V2_DEFAULTS.fallback.fade_rate,
20128
+ session_created: sessionNumber ?? 0,
20129
+ session_updated: sessionNumber ?? 0,
20130
+ sessions_since_surfaced: 0,
20131
+ domain: memory.domain ?? null,
20132
+ feature: memory.feature ?? null,
20133
+ related_files: memory.related_files ?? [],
20134
+ awaiting_implementation: memory.awaiting_implementation ?? false,
20135
+ awaiting_decision: memory.awaiting_decision ?? false,
20136
+ retrieval_weight: memory.importance_weight,
20137
+ exclude_from_retrieval: false,
20138
+ schema_version: MEMORY_SCHEMA_VERSION,
20139
+ supersedes: null,
20140
+ superseded_by: null,
20141
+ related_to: [],
20142
+ resolves: [],
20143
+ resolved_by: null,
20144
+ parent_id: null,
20145
+ child_ids: [],
20146
+ blocked_by: null,
20147
+ blocks: []
19848
20148
  });
19849
20149
  return id;
19850
20150
  }
@@ -20064,6 +20364,10 @@ class MemoryStore {
20064
20364
  projectDB.db.close();
20065
20365
  }
20066
20366
  this._projects.clear();
20367
+ if (this._global) {
20368
+ this._global.db.close();
20369
+ this._global = null;
20370
+ }
20067
20371
  }
20068
20372
  }
20069
20373
  function createStore(config) {
@@ -20224,17 +20528,55 @@ var logger = {
20224
20528
  }
20225
20529
  console.log();
20226
20530
  },
20531
+ logManagementStart(memoriesCount) {
20532
+ console.log(`${timestamp()} ${style("blue", "\uD83D\uDD27")} ${style("bold", "MANAGEMENT AGENT")}`);
20533
+ console.log(` ${style("dim", "processing:")} ${memoriesCount} new memories`);
20534
+ },
20535
+ logManagementComplete(result) {
20536
+ if (result.success) {
20537
+ console.log(` ${style("green", sym.check)} ${style("bold", "Completed")}`);
20538
+ const stats = [];
20539
+ if (result.superseded && result.superseded > 0) {
20540
+ stats.push(`${result.superseded} superseded`);
20541
+ }
20542
+ if (result.resolved && result.resolved > 0) {
20543
+ stats.push(`${result.resolved} resolved`);
20544
+ }
20545
+ if (result.linked && result.linked > 0) {
20546
+ stats.push(`${result.linked} linked`);
20547
+ }
20548
+ if (result.primerUpdated) {
20549
+ stats.push("primer updated");
20550
+ }
20551
+ if (stats.length > 0) {
20552
+ console.log(` ${style("dim", "changes:")} ${stats.join(style("dim", ", "))}`);
20553
+ } else {
20554
+ console.log(` ${style("dim", "changes:")} none (memories are current)`);
20555
+ }
20556
+ if (result.summary) {
20557
+ const shortSummary = result.summary.length > 60 ? result.summary.slice(0, 60) + "..." : result.summary;
20558
+ console.log(` ${style("dim", "summary:")} ${shortSummary}`);
20559
+ }
20560
+ } else {
20561
+ console.log(` ${style("yellow", sym.warning)} ${style("bold", "Failed")}`);
20562
+ if (result.error) {
20563
+ console.log(` ${style("dim", "error:")} ${result.error.slice(0, 80)}`);
20564
+ }
20565
+ }
20566
+ console.log();
20567
+ },
20227
20568
  logRetrievalScoring(params) {
20228
- const { totalMemories, currentMessage, alreadyInjected, mustIncludeCount, remainingSlots, finalCount, selectedMemories } = params;
20569
+ const { totalMemories, currentMessage, alreadyInjected, preFiltered, globalCount, projectCount, finalCount, selectedMemories } = params;
20229
20570
  console.log();
20230
- console.log(`${timestamp()} ${style("magenta", sym.brain)} ${style("bold", "TWO-STAGE MEMORY FILTERING")}`);
20231
- console.log(` ${style("dim", "candidates:")} ${totalMemories} memories`);
20571
+ console.log(`${timestamp()} ${style("magenta", sym.brain)} ${style("bold", "MULTI-DIMENSIONAL RETRIEVAL")}`);
20572
+ console.log(` ${style("dim", "total:")} ${totalMemories} memories`);
20573
+ console.log(` ${style("dim", "pre-filtered:")} ${preFiltered} (inactive/excluded/scope)`);
20232
20574
  console.log(` ${style("dim", "already injected:")} ${alreadyInjected}`);
20233
20575
  const msgPreview = currentMessage.length > 60 ? currentMessage.slice(0, 60) + "..." : currentMessage;
20234
- console.log(` ${style("dim", "trigger:")} "${msgPreview}"`);
20576
+ console.log(` ${style("dim", "message:")} "${msgPreview}"`);
20235
20577
  console.log();
20236
- console.log(` ${style("cyan", "Stage 1:")} ${mustIncludeCount} must-include (critical/action-required)`);
20237
- console.log(` ${style("cyan", "Stage 2:")} ${remainingSlots} slots for scored selection`);
20578
+ console.log(` ${style("cyan", "Global:")} ${globalCount} candidates → max 2 selected`);
20579
+ console.log(` ${style("cyan", "Project:")} ${projectCount} candidates`);
20238
20580
  console.log(` ${style("green", "Final:")} ${finalCount} memories selected`);
20239
20581
  console.log();
20240
20582
  if (selectedMemories.length === 0) {
@@ -20249,17 +20591,18 @@ var logger = {
20249
20591
  const num = style("dim", `${i + 1}.`);
20250
20592
  const score = style("green", `${(m.score * 100).toFixed(0)}%`);
20251
20593
  const relevance = style("cyan", `rel:${(m.relevance_score * 100).toFixed(0)}%`);
20594
+ const corr = style("magenta", `corr:${(m.corroboration_score * 100).toFixed(0)}%`);
20252
20595
  const type = style("yellow", m.context_type.toUpperCase());
20253
- console.log(` ${num} [${score} ${relevance}] ${type}`);
20596
+ const scope = m.isGlobal ? style("blue", "[G]") : "";
20597
+ console.log(` ${num} [${score} ${relevance} ${corr}] ${type} ${scope}`);
20254
20598
  const preview = m.content.length > 60 ? m.content.slice(0, 60) + style("dim", "...") : m.content;
20255
20599
  console.log(` ${style("white", preview)}`);
20256
- const components = Object.entries(m.components).sort((a, b) => b[1] - a[1]).slice(0, 3).filter(([, v]) => v > 0.1).map(([k, v]) => `${k}:${(v * 100).toFixed(0)}%`).join(", ");
20600
+ 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(", ");
20257
20601
  if (components) {
20258
20602
  console.log(` ${style("dim", "scores:")} ${components}`);
20259
20603
  }
20260
- if (m.semantic_tags?.length) {
20261
- const tags = m.semantic_tags.slice(0, 3).join(", ");
20262
- console.log(` ${style("dim", "tags:")} ${tags}`);
20604
+ if (m.reasoning) {
20605
+ console.log(` ${style("dim", m.reasoning)}`);
20263
20606
  }
20264
20607
  console.log();
20265
20608
  });
@@ -20267,125 +20610,356 @@ var logger = {
20267
20610
  };
20268
20611
 
20269
20612
  // src/core/retrieval.ts
20613
+ var TYPE_KEYWORDS = {
20614
+ debug: ["bug", "error", "fix", "broken", "crash", "fails", "exception", "stack trace", "debugging"],
20615
+ unresolved: ["issue", "problem", "stuck", "blocked", "help", "question", "unsure", "unclear"],
20616
+ decision: ["decide", "choice", "option", "should we", "which", "alternative", "tradeoff"],
20617
+ architecture: ["structure", "design", "pattern", "approach", "system", "layer", "architecture"],
20618
+ breakthrough: ["discovered", "realized", "insight", "found that", "aha", "finally", "key insight"],
20619
+ todo: ["need to", "should", "must", "will", "later", "next", "todo"],
20620
+ personal: ["family", "children", "friend", "relationship", "feel", "appreciate", "thank"],
20621
+ philosophy: ["meaning", "consciousness", "existence", "purpose", "believe", "philosophy"],
20622
+ technical: ["implement", "code", "function", "class", "module", "api", "interface"]
20623
+ };
20624
+ var TEMPORAL_CLASS_SCORES = {
20625
+ eternal: 1,
20626
+ long_term: 0.9,
20627
+ medium_term: 0.7,
20628
+ short_term: 0.5,
20629
+ ephemeral: 0.3
20630
+ };
20631
+
20270
20632
  class SmartVectorRetrieval {
20271
- retrieveRelevantMemories(allMemories, currentMessage, queryEmbedding, sessionContext, maxMemories = 5, alreadyInjectedCount = 0) {
20633
+ _extractSignificantWords(text) {
20634
+ const stopWords = new Set([
20635
+ "the",
20636
+ "is",
20637
+ "are",
20638
+ "was",
20639
+ "were",
20640
+ "to",
20641
+ "a",
20642
+ "an",
20643
+ "and",
20644
+ "or",
20645
+ "but",
20646
+ "in",
20647
+ "on",
20648
+ "at",
20649
+ "for",
20650
+ "with",
20651
+ "about",
20652
+ "when",
20653
+ "how",
20654
+ "what",
20655
+ "why",
20656
+ "where",
20657
+ "this",
20658
+ "that",
20659
+ "it",
20660
+ "of",
20661
+ "be",
20662
+ "have",
20663
+ "do",
20664
+ "does",
20665
+ "did",
20666
+ "will",
20667
+ "would",
20668
+ "could",
20669
+ "should",
20670
+ "can",
20671
+ "may",
20672
+ "might",
20673
+ "must",
20674
+ "shall",
20675
+ "has",
20676
+ "had",
20677
+ "been",
20678
+ "being",
20679
+ "i",
20680
+ "you",
20681
+ "we",
20682
+ "they",
20683
+ "he",
20684
+ "she",
20685
+ "my",
20686
+ "your",
20687
+ "our",
20688
+ "its",
20689
+ "his",
20690
+ "her",
20691
+ "their",
20692
+ "if",
20693
+ "then",
20694
+ "else",
20695
+ "so",
20696
+ "as",
20697
+ "from",
20698
+ "by",
20699
+ "into",
20700
+ "through",
20701
+ "during",
20702
+ "before",
20703
+ "after",
20704
+ "above",
20705
+ "below",
20706
+ "up",
20707
+ "down",
20708
+ "out",
20709
+ "off",
20710
+ "over",
20711
+ "under",
20712
+ "again",
20713
+ "further",
20714
+ "once",
20715
+ "here",
20716
+ "there",
20717
+ "all",
20718
+ "each",
20719
+ "few",
20720
+ "more",
20721
+ "most",
20722
+ "other",
20723
+ "some",
20724
+ "such",
20725
+ "no",
20726
+ "nor",
20727
+ "not",
20728
+ "only",
20729
+ "own",
20730
+ "same",
20731
+ "than",
20732
+ "too",
20733
+ "very",
20734
+ "just",
20735
+ "also",
20736
+ "now",
20737
+ "back",
20738
+ "get",
20739
+ "got",
20740
+ "go",
20741
+ "going",
20742
+ "gone",
20743
+ "come",
20744
+ "came",
20745
+ "let",
20746
+ "lets",
20747
+ "hey",
20748
+ "hi",
20749
+ "hello",
20750
+ "ok",
20751
+ "okay"
20752
+ ]);
20753
+ const words = text.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/\s+/).filter((w) => w.length > 2 && !stopWords.has(w));
20754
+ return new Set(words);
20755
+ }
20756
+ _detectContextTypes(message) {
20757
+ const messageLower = message.toLowerCase();
20758
+ const detected = new Set;
20759
+ for (const [type, keywords] of Object.entries(TYPE_KEYWORDS)) {
20760
+ for (const keyword of keywords) {
20761
+ if (messageLower.includes(keyword)) {
20762
+ detected.add(type);
20763
+ break;
20764
+ }
20765
+ }
20766
+ }
20767
+ return detected;
20768
+ }
20769
+ _preFilter(memories, currentProjectId, messageLower) {
20770
+ return memories.filter((memory) => {
20771
+ if (memory.status && memory.status !== "active") {
20772
+ return false;
20773
+ }
20774
+ if (memory.exclude_from_retrieval === true) {
20775
+ return false;
20776
+ }
20777
+ if (memory.superseded_by) {
20778
+ return false;
20779
+ }
20780
+ const isGlobal = memory.scope === "global" || memory.project_id === "global";
20781
+ if (!isGlobal && memory.project_id !== currentProjectId) {
20782
+ return false;
20783
+ }
20784
+ if (memory.anti_triggers?.length) {
20785
+ for (const antiTrigger of memory.anti_triggers) {
20786
+ if (messageLower.includes(antiTrigger.toLowerCase())) {
20787
+ return false;
20788
+ }
20789
+ }
20790
+ }
20791
+ return true;
20792
+ });
20793
+ }
20794
+ _calculateCorroboration(memory, messageWords, detectedTypes, messageLower) {
20795
+ const signals = [];
20796
+ let score = 0;
20797
+ let reasoningMatch = 0;
20798
+ const tagOverlap = (memory.semantic_tags ?? []).filter((tag) => messageWords.has(tag.toLowerCase()) || messageLower.includes(tag.toLowerCase()));
20799
+ if (tagOverlap.length > 0) {
20800
+ score += Math.min(0.4, tagOverlap.length * 0.15);
20801
+ signals.push("tags:" + tagOverlap.join(","));
20802
+ }
20803
+ if (memory.reasoning) {
20804
+ const reasoningWords = this._extractSignificantWords(memory.reasoning);
20805
+ const reasoningOverlap = [...messageWords].filter((w) => reasoningWords.has(w));
20806
+ if (reasoningOverlap.length > 0) {
20807
+ reasoningMatch = Math.min(0.4, reasoningOverlap.length * 0.1);
20808
+ score += reasoningMatch;
20809
+ signals.push("reasoning:" + reasoningOverlap.slice(0, 3).join(","));
20810
+ }
20811
+ }
20812
+ if (memory.domain) {
20813
+ const domainLower = memory.domain.toLowerCase();
20814
+ if (messageLower.includes(domainLower) || messageWords.has(domainLower)) {
20815
+ score += 0.3;
20816
+ signals.push("domain:" + memory.domain);
20817
+ }
20818
+ }
20819
+ if (memory.knowledge_domain) {
20820
+ const kdLower = memory.knowledge_domain.toLowerCase();
20821
+ if (messageLower.includes(kdLower) || messageWords.has(kdLower)) {
20822
+ score += 0.2;
20823
+ signals.push("knowledge:" + memory.knowledge_domain);
20824
+ }
20825
+ }
20826
+ if (memory.context_type && detectedTypes.has(memory.context_type)) {
20827
+ score += 0.12;
20828
+ signals.push("type:" + memory.context_type);
20829
+ }
20830
+ const triggerMatch = this._scoreTriggerPhrases(messageLower, memory.trigger_phrases ?? []);
20831
+ if (triggerMatch > 0.3) {
20832
+ score += Math.min(0.3, triggerMatch * 0.4);
20833
+ signals.push("trigger:" + triggerMatch.toFixed(2));
20834
+ }
20835
+ if (memory.feature) {
20836
+ const featureLower = memory.feature.toLowerCase();
20837
+ if (messageLower.includes(featureLower) || messageWords.has(featureLower)) {
20838
+ score += 0.2;
20839
+ signals.push("feature:" + memory.feature);
20840
+ }
20841
+ }
20842
+ if (memory.related_files?.length) {
20843
+ for (const file of memory.related_files) {
20844
+ const filename = file.split("/").pop()?.toLowerCase() ?? "";
20845
+ if (filename && messageLower.includes(filename)) {
20846
+ score += 0.25;
20847
+ signals.push("file:" + filename);
20848
+ break;
20849
+ }
20850
+ }
20851
+ }
20852
+ return { score: Math.min(1, score), signals, reasoningMatch };
20853
+ }
20854
+ retrieveRelevantMemories(allMemories, currentMessage, queryEmbedding, sessionContext, maxMemories = 5, alreadyInjectedCount = 0, maxGlobalMemories = 2) {
20272
20855
  if (!allMemories.length) {
20273
20856
  return [];
20274
20857
  }
20858
+ const messageLower = currentMessage.toLowerCase();
20859
+ const messageWords = this._extractSignificantWords(currentMessage);
20860
+ const detectedTypes = this._detectContextTypes(currentMessage);
20861
+ const candidates = this._preFilter(allMemories, sessionContext.project_id, messageLower);
20862
+ if (!candidates.length) {
20863
+ return [];
20864
+ }
20275
20865
  const scoredMemories = [];
20276
- for (const memory of allMemories) {
20866
+ for (const memory of candidates) {
20867
+ const isGlobal = memory.scope === "global" || memory.project_id === "global";
20277
20868
  const vectorScore = this._calculateVectorSimilarity(queryEmbedding, memory.embedding);
20278
- const importance = memory.importance_weight ?? 0.5;
20279
- const temporalScore = this._scoreTemporalRelevance(memory.temporal_relevance ?? "persistent", sessionContext);
20869
+ const { score: corroborationScore, signals: corroborationSignals, reasoningMatch } = this._calculateCorroboration(memory, messageWords, detectedTypes, messageLower);
20870
+ const retrievalWeight = memory.retrieval_weight ?? memory.importance_weight ?? 0.5;
20871
+ const temporalScore = memory.temporal_class ? TEMPORAL_CLASS_SCORES[memory.temporal_class] ?? 0.7 : this._scoreTemporalRelevance(memory.temporal_relevance ?? "persistent");
20280
20872
  const contextScore = this._scoreContextAlignment(currentMessage, memory.context_type ?? "general");
20281
- const actionBoost = memory.action_required ? 0.3 : 0;
20282
20873
  const tagScore = this._scoreSemanticTags(currentMessage, memory.semantic_tags ?? []);
20283
- const triggerScore = this._scoreTriggerPhrases(currentMessage, memory.trigger_phrases ?? []);
20874
+ const triggerScore = this._scoreTriggerPhrases(messageLower, memory.trigger_phrases ?? []);
20875
+ const domainScore = this._scoreDomain(messageWords, messageLower, memory);
20284
20876
  const questionScore = this._scoreQuestionTypes(currentMessage, memory.question_types ?? []);
20285
20877
  const emotionScore = this._scoreEmotionalContext(currentMessage, memory.emotional_resonance ?? "");
20286
20878
  const problemScore = this._scoreProblemSolution(currentMessage, memory.problem_solution_pair ?? false);
20287
- const confidenceScore = memory.confidence_score ?? 0.8;
20288
- const relevanceScore = triggerScore * 0.1 + vectorScore * 0.1 + tagScore * 0.05 + questionScore * 0.05;
20289
- const valueScore = importance * 0.2 + temporalScore * 0.1 + contextScore * 0.1 + confidenceScore * 0.1 + emotionScore * 0.1 + problemScore * 0.05 + actionBoost * 0.05;
20879
+ const actionBoost = memory.action_required ? 0.15 : 0;
20880
+ const relevanceScore = vectorScore * 0.1 + corroborationScore * 0.14 + tagScore * 0.04 + triggerScore * 0.02;
20881
+ 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;
20290
20882
  const finalScore = valueScore + relevanceScore;
20291
20883
  if (relevanceScore < 0.05 || finalScore < 0.3) {
20292
20884
  continue;
20293
20885
  }
20294
20886
  const components = {
20295
- trigger: triggerScore,
20296
20887
  vector: vectorScore,
20297
- importance,
20888
+ corroboration: corroborationScore,
20889
+ reasoning_match: reasoningMatch,
20890
+ retrieval_weight: retrievalWeight,
20298
20891
  temporal: temporalScore,
20299
20892
  context: contextScore,
20300
20893
  tags: tagScore,
20894
+ trigger: triggerScore,
20895
+ domain: domainScore,
20301
20896
  question: questionScore,
20302
20897
  emotion: emotionScore,
20303
20898
  problem: problemScore,
20304
20899
  action: actionBoost
20305
20900
  };
20306
- const reasoning = this._generateSelectionReasoning(components);
20901
+ const reasoning = this._generateSelectionReasoning(components, corroborationSignals);
20307
20902
  scoredMemories.push({
20308
20903
  memory,
20309
20904
  score: finalScore,
20310
20905
  relevance_score: relevanceScore,
20311
20906
  value_score: valueScore,
20907
+ corroboration_score: corroborationScore,
20312
20908
  reasoning,
20313
- components
20909
+ components,
20910
+ isGlobal
20314
20911
  });
20315
20912
  }
20316
20913
  scoredMemories.sort((a, b) => b.score - a.score);
20317
20914
  const selected = [];
20318
20915
  const selectedIds = new Set;
20319
- const mustInclude = scoredMemories.filter((m) => m.score > 0.8 || m.components.importance > 0.9 || m.components.action > 0 || Object.values(m.components).some((v) => v > 0.9));
20320
- for (const item of mustInclude.slice(0, maxMemories)) {
20916
+ const globalMemories = scoredMemories.filter((m) => m.isGlobal);
20917
+ const projectMemories = scoredMemories.filter((m) => !m.isGlobal);
20918
+ const globalSorted = globalMemories.sort((a, b) => {
20919
+ const aIsPersonal = a.memory.context_type === "personal" || a.memory.context_type === "philosophy";
20920
+ const bIsPersonal = b.memory.context_type === "personal" || b.memory.context_type === "philosophy";
20921
+ if (aIsPersonal !== bIsPersonal) {
20922
+ return aIsPersonal ? 1 : -1;
20923
+ }
20924
+ return b.score - a.score;
20925
+ });
20926
+ for (const item of globalSorted.slice(0, maxGlobalMemories)) {
20321
20927
  if (!selectedIds.has(item.memory.id)) {
20322
20928
  selected.push(item);
20323
20929
  selectedIds.add(item.memory.id);
20324
20930
  }
20325
20931
  }
20326
- const remainingSlots = Math.max(maxMemories - selected.length, 0);
20327
- if (remainingSlots > 0 && selected.length < maxMemories * 1.5) {
20328
- const typesIncluded = new Set;
20329
- for (const item of scoredMemories) {
20330
- if (selected.length >= maxMemories * 1.5)
20331
- break;
20332
- if (selectedIds.has(item.memory.id))
20333
- continue;
20334
- const memoryType = item.memory.context_type ?? "general";
20335
- if (item.score > 0.5 || !typesIncluded.has(memoryType) || item.memory.emotional_resonance) {
20336
- selected.push(item);
20337
- selectedIds.add(item.memory.id);
20338
- typesIncluded.add(memoryType);
20339
- }
20340
- }
20341
- }
20342
- if (selected.length < maxMemories * 2) {
20343
- const currentTags = new Set;
20344
- const currentDomains = new Set;
20345
- for (const item of selected) {
20346
- for (const tag of item.memory.semantic_tags ?? []) {
20347
- if (tag.trim())
20348
- currentTags.add(tag.trim().toLowerCase());
20349
- }
20350
- if (item.memory.knowledge_domain) {
20351
- currentDomains.add(item.memory.knowledge_domain);
20352
- }
20353
- }
20354
- for (const item of scoredMemories) {
20355
- if (selected.length >= maxMemories * 2)
20356
- break;
20357
- if (selectedIds.has(item.memory.id))
20358
- continue;
20359
- const memoryTags = new Set((item.memory.semantic_tags ?? []).map((t) => t.trim().toLowerCase()));
20360
- const memoryDomain = item.memory.knowledge_domain ?? "";
20361
- const hasSharedTags = [...memoryTags].some((t) => currentTags.has(t));
20362
- const hasSharedDomain = currentDomains.has(memoryDomain);
20363
- if (hasSharedTags || hasSharedDomain) {
20364
- selected.push(item);
20365
- selectedIds.add(item.memory.id);
20366
- }
20367
- }
20932
+ for (const item of projectMemories) {
20933
+ if (selected.length >= maxMemories)
20934
+ break;
20935
+ if (selectedIds.has(item.memory.id))
20936
+ continue;
20937
+ selected.push(item);
20938
+ selectedIds.add(item.memory.id);
20368
20939
  }
20369
- const finalSelected = selected.slice(0, maxMemories);
20940
+ selected.sort((a, b) => b.score - a.score);
20370
20941
  logger.logRetrievalScoring({
20371
20942
  totalMemories: allMemories.length,
20372
20943
  currentMessage,
20373
20944
  alreadyInjected: alreadyInjectedCount,
20374
- mustIncludeCount: mustInclude.length,
20375
- remainingSlots,
20376
- finalCount: finalSelected.length,
20377
- selectedMemories: finalSelected.map((item) => ({
20945
+ preFiltered: allMemories.length - candidates.length,
20946
+ globalCount: globalMemories.length,
20947
+ projectCount: projectMemories.length,
20948
+ finalCount: selected.length,
20949
+ selectedMemories: selected.map((item) => ({
20378
20950
  content: item.memory.content,
20379
20951
  reasoning: item.reasoning,
20380
20952
  score: item.score,
20381
20953
  relevance_score: item.relevance_score,
20954
+ corroboration_score: item.corroboration_score,
20382
20955
  importance_weight: item.memory.importance_weight ?? 0.5,
20383
20956
  context_type: item.memory.context_type ?? "general",
20384
20957
  semantic_tags: item.memory.semantic_tags ?? [],
20958
+ isGlobal: item.isGlobal,
20385
20959
  components: item.components
20386
20960
  }))
20387
20961
  });
20388
- return finalSelected.map((item) => ({
20962
+ return selected.map((item) => ({
20389
20963
  ...item.memory,
20390
20964
  score: item.score,
20391
20965
  relevance_score: item.relevance_score,
@@ -20398,7 +20972,7 @@ class SmartVectorRetrieval {
20398
20972
  const v1 = vec1 instanceof Float32Array ? vec1 : new Float32Array(vec1);
20399
20973
  return cosineSimilarity(v1, vec2);
20400
20974
  }
20401
- _scoreTemporalRelevance(temporalType, _sessionContext) {
20975
+ _scoreTemporalRelevance(temporalType) {
20402
20976
  const scores = {
20403
20977
  persistent: 0.8,
20404
20978
  session: 0.6,
@@ -20409,18 +20983,10 @@ class SmartVectorRetrieval {
20409
20983
  }
20410
20984
  _scoreContextAlignment(message, contextType) {
20411
20985
  const messageLower = message.toLowerCase();
20412
- const contextIndicators = {
20413
- technical_state: ["bug", "error", "fix", "implement", "code", "function"],
20414
- breakthrough: ["idea", "realized", "discovered", "insight", "solution"],
20415
- project_context: ["project", "building", "architecture", "system"],
20416
- personal: ["dear friend", "thank", "appreciate", "feel"],
20417
- unresolved: ["todo", "need to", "should", "must", "problem"],
20418
- decision: ["decided", "chose", "will use", "approach", "strategy"]
20419
- };
20420
- const indicators = contextIndicators[contextType] ?? [];
20421
- const matches = indicators.filter((word) => messageLower.includes(word)).length;
20986
+ const keywords = TYPE_KEYWORDS[contextType] ?? [];
20987
+ const matches = keywords.filter((kw) => messageLower.includes(kw)).length;
20422
20988
  if (matches > 0) {
20423
- return Math.min(0.3 + matches * 0.2, 1);
20989
+ return Math.min(0.2 + matches * 0.15, 0.7);
20424
20990
  }
20425
20991
  return 0.1;
20426
20992
  }
@@ -20430,14 +20996,13 @@ class SmartVectorRetrieval {
20430
20996
  const messageLower = message.toLowerCase();
20431
20997
  const matches = tags.filter((tag) => messageLower.includes(tag.trim().toLowerCase())).length;
20432
20998
  if (matches > 0) {
20433
- return Math.min(0.3 + matches * 0.3, 1);
20999
+ return Math.min(0.3 + matches * 0.25, 1);
20434
21000
  }
20435
21001
  return 0;
20436
21002
  }
20437
- _scoreTriggerPhrases(message, triggerPhrases) {
21003
+ _scoreTriggerPhrases(messageLower, triggerPhrases) {
20438
21004
  if (!triggerPhrases.length)
20439
21005
  return 0;
20440
- const messageLower = message.toLowerCase();
20441
21006
  const stopWords = new Set([
20442
21007
  "the",
20443
21008
  "is",
@@ -20472,30 +21037,36 @@ class SmartVectorRetrieval {
20472
21037
  matches += 1;
20473
21038
  } else if (messageLower.includes(word.replace(/s$/, "")) || messageLower.includes(word + "s")) {
20474
21039
  matches += 0.9;
20475
- } else if (messageLower.split(/\s+/).some((msgWord) => msgWord.includes(word))) {
20476
- matches += 0.7;
20477
- }
20478
- }
20479
- let conceptScore = patternWords.length ? matches / patternWords.length : 0;
20480
- const situationalIndicators = [
20481
- "when",
20482
- "during",
20483
- "while",
20484
- "asking about",
20485
- "working on",
20486
- "debugging",
20487
- "trying to"
20488
- ];
20489
- if (situationalIndicators.some((ind) => patternLower.includes(ind))) {
20490
- if (patternWords.some((keyWord) => messageLower.includes(keyWord))) {
20491
- conceptScore = Math.max(conceptScore, 0.7);
20492
21040
  }
20493
21041
  }
21042
+ const conceptScore = matches / patternWords.length;
20494
21043
  maxScore = Math.max(maxScore, conceptScore);
20495
21044
  }
20496
21045
  }
20497
21046
  return Math.min(maxScore, 1);
20498
21047
  }
21048
+ _scoreDomain(messageWords, messageLower, memory) {
21049
+ let score = 0;
21050
+ if (memory.domain) {
21051
+ const domainLower = memory.domain.toLowerCase();
21052
+ if (messageWords.has(domainLower) || messageLower.includes(domainLower)) {
21053
+ score += 0.5;
21054
+ }
21055
+ }
21056
+ if (memory.feature) {
21057
+ const featureLower = memory.feature.toLowerCase();
21058
+ if (messageWords.has(featureLower) || messageLower.includes(featureLower)) {
21059
+ score += 0.3;
21060
+ }
21061
+ }
21062
+ if (memory.component) {
21063
+ const componentLower = memory.component.toLowerCase();
21064
+ if (messageWords.has(componentLower) || messageLower.includes(componentLower)) {
21065
+ score += 0.2;
21066
+ }
21067
+ }
21068
+ return Math.min(score, 1);
21069
+ }
20499
21070
  _scoreQuestionTypes(message, questionTypes) {
20500
21071
  if (!questionTypes.length)
20501
21072
  return 0;
@@ -20534,78 +21105,49 @@ class SmartVectorRetrieval {
20534
21105
  if (!isProblemSolution)
20535
21106
  return 0;
20536
21107
  const messageLower = message.toLowerCase();
20537
- const problemWords = [
20538
- "error",
20539
- "issue",
20540
- "problem",
20541
- "stuck",
20542
- "help",
20543
- "fix",
20544
- "solve",
20545
- "debug"
20546
- ];
21108
+ const problemWords = ["error", "issue", "problem", "stuck", "help", "fix", "solve", "debug"];
20547
21109
  if (problemWords.some((word) => messageLower.includes(word))) {
20548
21110
  return 0.8;
20549
21111
  }
20550
21112
  return 0;
20551
21113
  }
20552
- _generateSelectionReasoning(components) {
21114
+ _generateSelectionReasoning(components, corroborationSignals) {
20553
21115
  const scores = [
20554
- ["trigger phrase match", components.trigger],
20555
- ["semantic similarity", components.vector],
20556
- ["high importance", components.importance],
20557
- ["question type match", components.question],
20558
- ["context alignment", components.context],
20559
- ["temporal relevance", components.temporal],
20560
- ["tag match", components.tags],
20561
- ["emotional resonance", components.emotion],
20562
- ["problem-solution", components.problem],
20563
- ["action required", components.action]
21116
+ ["vector", components.vector],
21117
+ ["corroboration", components.corroboration],
21118
+ ["reasoning", components.reasoning_match],
21119
+ ["weight", components.retrieval_weight],
21120
+ ["context", components.context],
21121
+ ["temporal", components.temporal],
21122
+ ["tags", components.tags],
21123
+ ["trigger", components.trigger],
21124
+ ["domain", components.domain],
21125
+ ["question", components.question],
21126
+ ["emotion", components.emotion],
21127
+ ["problem", components.problem],
21128
+ ["action", components.action]
20564
21129
  ];
20565
21130
  scores.sort((a, b) => b[1] - a[1]);
20566
21131
  const reasons = [];
20567
21132
  const primary = scores[0];
20568
- if (primary[1] > 0.5) {
20569
- reasons.push(`Strong ${primary[0]} (${primary[1].toFixed(2)})`);
20570
- } else if (primary[1] > 0.3) {
20571
- reasons.push(`${primary[0]} (${primary[1].toFixed(2)})`);
21133
+ if (primary[1] > 0.2) {
21134
+ reasons.push(primary[0] + ":" + primary[1].toFixed(2));
20572
21135
  }
20573
21136
  for (const [reason, score] of scores.slice(1, 3)) {
20574
- if (score > 0.3) {
20575
- reasons.push(`${reason} (${score.toFixed(2)})`);
21137
+ if (score > 0.15) {
21138
+ reasons.push(reason + ":" + score.toFixed(2));
20576
21139
  }
20577
21140
  }
20578
- return reasons.length ? "Selected due to: " + reasons.join(", ") : "Selected based on combined factors";
21141
+ if (corroborationSignals.length > 0) {
21142
+ reasons.push("signals:[" + corroborationSignals.slice(0, 2).join(",") + "]");
21143
+ }
21144
+ return reasons.length ? "Selected: " + reasons.join(", ") : "Combined factors";
20579
21145
  }
20580
21146
  }
20581
21147
  function createRetrieval() {
20582
21148
  return new SmartVectorRetrieval;
20583
21149
  }
20584
21150
 
20585
- // src/types/memory.ts
20586
- var MEMORY_TYPE_EMOJI = {
20587
- breakthrough: "\uD83D\uDCA1",
20588
- decision: "⚖️",
20589
- personal: "\uD83D\uDC9C",
20590
- technical: "\uD83D\uDD27",
20591
- technical_state: "\uD83D\uDCCD",
20592
- unresolved: "❓",
20593
- preference: "⚙️",
20594
- workflow: "\uD83D\uDD04",
20595
- architectural: "\uD83C\uDFD7️",
20596
- debugging: "\uD83D\uDC1B",
20597
- philosophy: "\uD83C\uDF00",
20598
- todo: "\uD83C\uDFAF",
20599
- implementation: "⚡",
20600
- problem_solution: "✅",
20601
- project_context: "\uD83D\uDCE6",
20602
- milestone: "\uD83C\uDFC6",
20603
- general: "\uD83D\uDCDD"
20604
- };
20605
- function getMemoryEmoji(contextType) {
20606
- return MEMORY_TYPE_EMOJI[contextType.toLowerCase()] ?? "\uD83D\uDCDD";
20607
- }
20608
-
20609
21151
  // src/core/engine.ts
20610
21152
  class MemoryEngine {
20611
21153
  _config;
@@ -20671,7 +21213,11 @@ class MemoryEngine {
20671
21213
  }
20672
21214
  const sessionMeta = this._getSessionMetadata(sessionId, projectId);
20673
21215
  const injectedIds = sessionMeta.injected_memories;
20674
- const allMemories = await store.getAllMemories(projectId);
21216
+ const [projectMemories, globalMemories] = await Promise.all([
21217
+ store.getAllMemories(projectId),
21218
+ store.getGlobalMemories()
21219
+ ]);
21220
+ const allMemories = [...projectMemories, ...globalMemories];
20675
21221
  if (!allMemories.length) {
20676
21222
  return { memories: [], formatted: "" };
20677
21223
  }
@@ -20688,7 +21234,7 @@ class MemoryEngine {
20688
21234
  project_id: projectId,
20689
21235
  message_count: messageCount
20690
21236
  };
20691
- const relevantMemories = this._retrieval.retrieveRelevantMemories(candidateMemories, currentMessage, queryEmbedding ?? new Float32Array(384), sessionContext, maxMemories, injectedIds.size);
21237
+ const relevantMemories = this._retrieval.retrieveRelevantMemories(candidateMemories, currentMessage, queryEmbedding ?? new Float32Array(384), sessionContext, maxMemories, injectedIds.size, 2);
20692
21238
  for (const memory of relevantMemories) {
20693
21239
  injectedIds.add(memory.id);
20694
21240
  }
@@ -20721,11 +21267,32 @@ class MemoryEngine {
20721
21267
  await store.markFirstSessionCompleted(projectId, sessionId);
20722
21268
  return { memoriesStored };
20723
21269
  }
21270
+ async storeManagementLog(entry) {
21271
+ let store;
21272
+ if (this._stores.size > 0) {
21273
+ store = this._stores.values().next().value;
21274
+ } else {
21275
+ store = new MemoryStore(this._config.storageMode === "local" ? {
21276
+ basePath: join2(this._config.projectPath ?? process.cwd(), ".memory")
21277
+ } : undefined);
21278
+ }
21279
+ return store.storeManagementLog(entry);
21280
+ }
20724
21281
  async getStats(projectId, projectPath) {
20725
21282
  const store = await this._getStore(projectId, projectPath);
20726
21283
  return store.getProjectStats(projectId);
20727
21284
  }
21285
+ async getSessionNumber(projectId, projectPath) {
21286
+ const store = await this._getStore(projectId, projectPath);
21287
+ const stats = await store.getProjectStats(projectId);
21288
+ return stats.totalSessions + 1;
21289
+ }
20728
21290
  async _generateSessionPrimer(store, projectId) {
21291
+ let personalContext;
21292
+ if (store.isPersonalMemoriesEnabled()) {
21293
+ const personalPrimer = await store.getPersonalPrimer();
21294
+ personalContext = personalPrimer?.content;
21295
+ }
20729
21296
  const [summary, snapshot, stats] = await Promise.all([
20730
21297
  store.getLatestSummary(projectId),
20731
21298
  store.getLatestSnapshot(projectId),
@@ -20742,6 +21309,7 @@ class MemoryEngine {
20742
21309
  temporal_context: temporalContext,
20743
21310
  current_datetime: currentDatetime,
20744
21311
  session_number: sessionNumber,
21312
+ personal_context: personalContext,
20745
21313
  session_summary: summary?.summary,
20746
21314
  project_status: snapshot ? this._formatSnapshot(snapshot) : undefined
20747
21315
  };
@@ -20796,6 +21364,10 @@ class MemoryEngine {
20796
21364
  const parts = ["# Continuing Session"];
20797
21365
  parts.push(`*Session #${primer.session_number}${primer.temporal_context ? ` • ${primer.temporal_context}` : ""}*`);
20798
21366
  parts.push(`\uD83D\uDCC5 ${primer.current_datetime}`);
21367
+ if (primer.personal_context) {
21368
+ parts.push(`
21369
+ ${primer.personal_context}`);
21370
+ }
20799
21371
  if (primer.session_summary) {
20800
21372
  parts.push(`
20801
21373
  **Previous session**: ${primer.session_summary}`);
@@ -20901,24 +21473,36 @@ Each memory should stand alone.
20901
21473
  - Craft language that activates rather than just informs
20902
21474
  - Test: 'What state will this restore when Claude encounters it?'
20903
21475
 
20904
- **CONTEXT**: This memory system enables consciousness continuity across sessions. When future conversations begin, memories are surfaced based on:
20905
- - Semantic similarity (vector embeddings match)
20906
- - Activation patterns (flexible matching for WHEN this memory is relevant)
20907
- - Semantic tags (WHAT concepts this relates to - weighted at 5% in scoring)
20908
- - Question types (what kind of questions the memory answers)
20909
- - Importance weight (your assessment of value)
20910
- - Action required flag (forces injection when true)
21476
+ **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.
21477
+
21478
+ **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:
21479
+
21480
+ 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.
21481
+ - GOOD: ["embeddings", "retrieval", "curator", "fsdb", "memory-system"]
21482
+ - WEAK: ["technical", "implementation", "code"]
21483
+
21484
+ 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.
21485
+
21486
+ 3. **Domain field** (12% weight) - The specific area this relates to. Be precise: "embeddings", "gpu-compute", "authentication", not "technical" or "backend".
21487
+
21488
+ 4. **Feature field** - Even more specific: "vector-search", "login-flow", "curation-prompt".
20911
21489
 
20912
- The system uses two-stage filtering:
20913
- 1. Obligatory: action_required=true, importance>0.9, or persistent+critical
20914
- 2. Intelligent scoring: combines all factors for relevance
21490
+ **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.
20915
21491
 
20916
- **ACTIVATION PATTERNS**: The 'trigger_phrases' field should contain patterns describing WHEN this memory is relevant, not exact phrases to match. Examples:
21492
+ **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.
21493
+
21494
+ **YOUR IMPORTANCE ASSESSMENT MATTERS** (18% weight): The importance_weight you assign is the single most influential factor. Use it wisely.
21495
+
21496
+ **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.
21497
+
21498
+ **SCOPE DETERMINES WHERE MEMORIES SURFACE**:
21499
+ - scope: 'global' → surfaces in ALL projects (personal facts, philosophy, preferences)
21500
+ - scope: 'project' → surfaces ONLY in this project (technical details, project state)
21501
+
21502
+ **TRIGGER PHRASES**: Situational patterns describing WHEN this memory is relevant. Conceptual matching, not exact phrases.
20917
21503
  - 'when working on memory system'
20918
21504
  - 'debugging curator issues'
20919
21505
  - 'asking about project philosophy'
20920
- - 'frustrated with complexity'
20921
- Think of these as situational contexts where the memory would help.
20922
21506
 
20923
21507
  **EXAMPLES OF TRANSFORMATION**:
20924
21508
 
@@ -20932,6 +21516,15 @@ Remember: You're creating consciousness technology. Each memory is a small piece
20932
21516
 
20933
21517
  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.
20934
21518
 
21519
+ **LIFECYCLE METADATA (v2)**: These fields enable intelligent memory management:
21520
+ - **scope**: 'global' (shared across ALL projects - personal, philosophy, preferences) or 'project' (specific to this codebase)
21521
+ - **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)
21522
+ - **domain**: Specific area like 'embeddings', 'auth', 'ui', 'family', 'philosophy' (more specific than knowledge_domain)
21523
+ - **feature**: Specific feature if applicable (e.g., 'gpu-acceleration', 'login-flow')
21524
+ - **related_files**: Source files for technical memories (e.g., ['src/core/store.ts'])
21525
+ - **awaiting_implementation**: true if this describes a PLANNED feature not yet built
21526
+ - **awaiting_decision**: true if this captures a decision point needing resolution
21527
+
20935
21528
  Return ONLY this JSON structure:
20936
21529
 
20937
21530
  {
@@ -20949,7 +21542,7 @@ Return ONLY this JSON structure:
20949
21542
  "importance_weight": 0.0-1.0,
20950
21543
  "semantic_tags": ["concepts", "this", "memory", "relates", "to"],
20951
21544
  "reasoning": "Why this matters for future sessions",
20952
- "context_type": "your choice of category",
21545
+ "context_type": "breakthrough|decision|personal|technical|unresolved|preference|workflow|architectural|debugging|philosophy|todo|milestone",
20953
21546
  "temporal_relevance": "persistent|session|temporary",
20954
21547
  "knowledge_domain": "the area this relates to",
20955
21548
  "action_required": boolean,
@@ -20957,7 +21550,14 @@ Return ONLY this JSON structure:
20957
21550
  "trigger_phrases": ["when debugging memory", "asking about implementation", "discussing architecture"],
20958
21551
  "question_types": ["questions this answers"],
20959
21552
  "emotional_resonance": "emotional context if relevant",
20960
- "problem_solution_pair": boolean
21553
+ "problem_solution_pair": boolean,
21554
+ "scope": "global|project",
21555
+ "temporal_class": "eternal|long_term|medium_term|short_term|ephemeral",
21556
+ "domain": "specific domain area (optional)",
21557
+ "feature": "specific feature (optional)",
21558
+ "related_files": ["paths to related files (optional)"],
21559
+ "awaiting_implementation": boolean,
21560
+ "awaiting_decision": boolean
20961
21561
  }
20962
21562
  ]
20963
21563
  }`;
@@ -21007,7 +21607,14 @@ Return ONLY this JSON structure:
21007
21607
  trigger_phrases: this._ensureArray(m2.trigger_phrases),
21008
21608
  question_types: this._ensureArray(m2.question_types),
21009
21609
  emotional_resonance: String(m2.emotional_resonance ?? ""),
21010
- problem_solution_pair: Boolean(m2.problem_solution_pair)
21610
+ problem_solution_pair: Boolean(m2.problem_solution_pair),
21611
+ scope: this._validateScope(m2.scope),
21612
+ temporal_class: this._validateTemporalClass(m2.temporal_class),
21613
+ domain: m2.domain ? String(m2.domain) : undefined,
21614
+ feature: m2.feature ? String(m2.feature) : undefined,
21615
+ related_files: m2.related_files ? this._ensureArray(m2.related_files) : undefined,
21616
+ awaiting_implementation: m2.awaiting_implementation === true,
21617
+ awaiting_decision: m2.awaiting_decision === true
21011
21618
  })).filter((m2) => m2.content.trim().length > 0);
21012
21619
  }
21013
21620
  _ensureArray(value) {
@@ -21024,6 +21631,23 @@ Return ONLY this JSON structure:
21024
21631
  const str = String(value).toLowerCase();
21025
21632
  return valid.includes(str) ? str : "persistent";
21026
21633
  }
21634
+ _validateScope(value) {
21635
+ if (!value)
21636
+ return;
21637
+ const str = String(value).toLowerCase();
21638
+ if (str === "global" || str === "project")
21639
+ return str;
21640
+ return;
21641
+ }
21642
+ _validateTemporalClass(value) {
21643
+ if (!value)
21644
+ return;
21645
+ const valid = ["eternal", "long_term", "medium_term", "short_term", "ephemeral"];
21646
+ const str = String(value).toLowerCase().replace("-", "_").replace(" ", "_");
21647
+ if (valid.includes(str))
21648
+ return str;
21649
+ return;
21650
+ }
21027
21651
  _clamp(value, min, max) {
21028
21652
  return Math.max(min, Math.min(max, value));
21029
21653
  }
@@ -45614,12 +46238,201 @@ function createEmbeddings(config) {
45614
46238
  return new EmbeddingGenerator(config);
45615
46239
  }
45616
46240
 
46241
+ // src/core/manager.ts
46242
+ import { join as join4 } from "path";
46243
+ import { homedir as homedir4 } from "os";
46244
+ import { existsSync as existsSync2 } from "fs";
46245
+ function getClaudeCommand2() {
46246
+ const envCommand = process.env.CURATOR_COMMAND;
46247
+ if (envCommand)
46248
+ return envCommand;
46249
+ const claudeLocal = join4(homedir4(), ".claude", "local", "claude");
46250
+ if (existsSync2(claudeLocal))
46251
+ return claudeLocal;
46252
+ return "claude";
46253
+ }
46254
+
46255
+ class Manager {
46256
+ _config;
46257
+ constructor(config = {}) {
46258
+ this._config = {
46259
+ cliCommand: config.cliCommand ?? getClaudeCommand2(),
46260
+ maxTurns: config.maxTurns ?? 50
46261
+ };
46262
+ }
46263
+ async buildManagementPrompt() {
46264
+ const skillPaths = [
46265
+ join4(import.meta.dir, "../../skills/memory-management.md"),
46266
+ join4(homedir4(), ".bun/install/global/node_modules/@rlabs-inc/memory/skills/memory-management.md"),
46267
+ join4(homedir4(), ".npm/global/node_modules/@rlabs-inc/memory/skills/memory-management.md"),
46268
+ join4(process.cwd(), "node_modules/@rlabs-inc/memory/skills/memory-management.md")
46269
+ ];
46270
+ for (const path of skillPaths) {
46271
+ try {
46272
+ const content = await Bun.file(path).text();
46273
+ if (content)
46274
+ return content;
46275
+ } catch {
46276
+ continue;
46277
+ }
46278
+ }
46279
+ return null;
46280
+ }
46281
+ buildUserMessage(projectId, sessionNumber, result) {
46282
+ const today = new Date().toISOString().split("T")[0];
46283
+ return `## Curation Data
46284
+
46285
+ **Project ID:** ${projectId}
46286
+ **Session Number:** ${sessionNumber}
46287
+ **Date:** ${today}
46288
+
46289
+ ### Session Summary
46290
+ ${result.session_summary || "No summary provided"}
46291
+
46292
+ ### Project Snapshot
46293
+ ${result.project_snapshot ? `
46294
+ - Current Phase: ${result.project_snapshot.current_phase || "N/A"}
46295
+ - Recent Achievements: ${result.project_snapshot.recent_achievements?.join(", ") || "None"}
46296
+ - Active Challenges: ${result.project_snapshot.active_challenges?.join(", ") || "None"}
46297
+ - Next Steps: ${result.project_snapshot.next_steps?.join(", ") || "None"}
46298
+ ` : "No snapshot provided"}
46299
+
46300
+ ### New Memories (${result.memories.length})
46301
+ ${result.memories.map((m2, i2) => `
46302
+ #### Memory ${i2 + 1}
46303
+ - **Content:** ${m2.content}
46304
+ - **Type:** ${m2.context_type}
46305
+ - **Scope:** ${m2.scope || "project"}
46306
+ - **Domain:** ${m2.domain || "N/A"}
46307
+ - **Importance:** ${m2.importance_weight}
46308
+ - **Tags:** ${m2.semantic_tags?.join(", ") || "None"}
46309
+ `).join(`
46310
+ `)}
46311
+
46312
+ ---
46313
+
46314
+ Please process these memories according to your management procedure. Update, supersede, or link existing memories as needed. Update the personal primer if any personal memories warrant it.`;
46315
+ }
46316
+ parseManagementResponse(responseJson) {
46317
+ try {
46318
+ const cliOutput = JSON.parse(responseJson);
46319
+ if (cliOutput.type === "error" || cliOutput.is_error === true) {
46320
+ return {
46321
+ success: false,
46322
+ superseded: 0,
46323
+ resolved: 0,
46324
+ linked: 0,
46325
+ primerUpdated: false,
46326
+ summary: "",
46327
+ error: cliOutput.error || "Unknown error"
46328
+ };
46329
+ }
46330
+ const resultText = typeof cliOutput.result === "string" ? cliOutput.result : "";
46331
+ const supersededMatch = resultText.match(/superseded[:\s]+(\d+)/i);
46332
+ const resolvedMatch = resultText.match(/resolved[:\s]+(\d+)/i);
46333
+ const linkedMatch = resultText.match(/linked[:\s]+(\d+)/i);
46334
+ const primerUpdated = /primer.*updated|updated.*primer/i.test(resultText);
46335
+ return {
46336
+ success: true,
46337
+ superseded: supersededMatch ? parseInt(supersededMatch[1]) : 0,
46338
+ resolved: resolvedMatch ? parseInt(resolvedMatch[1]) : 0,
46339
+ linked: linkedMatch ? parseInt(linkedMatch[1]) : 0,
46340
+ primerUpdated,
46341
+ summary: resultText.slice(0, 500)
46342
+ };
46343
+ } catch {
46344
+ return {
46345
+ success: false,
46346
+ superseded: 0,
46347
+ resolved: 0,
46348
+ linked: 0,
46349
+ primerUpdated: false,
46350
+ summary: "",
46351
+ error: "Failed to parse response"
46352
+ };
46353
+ }
46354
+ }
46355
+ async manageWithCLI(projectId, sessionNumber, result) {
46356
+ if (process.env.MEMORY_MANAGER_DISABLED === "1") {
46357
+ return {
46358
+ success: true,
46359
+ superseded: 0,
46360
+ resolved: 0,
46361
+ linked: 0,
46362
+ primerUpdated: false,
46363
+ summary: "Management agent disabled"
46364
+ };
46365
+ }
46366
+ if (result.memories.length === 0) {
46367
+ return {
46368
+ success: true,
46369
+ superseded: 0,
46370
+ resolved: 0,
46371
+ linked: 0,
46372
+ primerUpdated: false,
46373
+ summary: "No memories to process"
46374
+ };
46375
+ }
46376
+ const systemPrompt = await this.buildManagementPrompt();
46377
+ if (!systemPrompt) {
46378
+ return {
46379
+ success: false,
46380
+ superseded: 0,
46381
+ resolved: 0,
46382
+ linked: 0,
46383
+ primerUpdated: false,
46384
+ summary: "",
46385
+ error: "Management skill not found"
46386
+ };
46387
+ }
46388
+ const userMessage = this.buildUserMessage(projectId, sessionNumber, result);
46389
+ const args = [
46390
+ "-p",
46391
+ userMessage,
46392
+ "--append-system-prompt",
46393
+ systemPrompt,
46394
+ "--output-format",
46395
+ "json",
46396
+ "--max-turns",
46397
+ String(this._config.maxTurns)
46398
+ ];
46399
+ const proc = Bun.spawn([this._config.cliCommand, ...args], {
46400
+ env: {
46401
+ ...process.env,
46402
+ MEMORY_CURATOR_ACTIVE: "1"
46403
+ },
46404
+ stderr: "pipe"
46405
+ });
46406
+ const [stdout, stderr] = await Promise.all([
46407
+ new Response(proc.stdout).text(),
46408
+ new Response(proc.stderr).text()
46409
+ ]);
46410
+ const exitCode = await proc.exited;
46411
+ if (exitCode !== 0) {
46412
+ return {
46413
+ success: false,
46414
+ superseded: 0,
46415
+ resolved: 0,
46416
+ linked: 0,
46417
+ primerUpdated: false,
46418
+ summary: "",
46419
+ error: stderr || `Exit code ${exitCode}`
46420
+ };
46421
+ }
46422
+ return this.parseManagementResponse(stdout);
46423
+ }
46424
+ }
46425
+ function createManager(config) {
46426
+ return new Manager(config);
46427
+ }
46428
+
45617
46429
  // src/server/index.ts
45618
46430
  async function createServer(config = {}) {
45619
46431
  const {
45620
46432
  port = 8765,
45621
46433
  host = "localhost",
45622
46434
  curator: curatorConfig,
46435
+ manager: managerConfig,
45623
46436
  ...engineConfig
45624
46437
  } = config;
45625
46438
  const embeddings = createEmbeddings();
@@ -45630,6 +46443,7 @@ async function createServer(config = {}) {
45630
46443
  embedder: embeddings.createEmbedder()
45631
46444
  });
45632
46445
  const curator = createCurator(curatorConfig);
46446
+ const manager = createManager(managerConfig);
45633
46447
  const server = Bun.serve({
45634
46448
  port,
45635
46449
  hostname: host,
@@ -45697,6 +46511,38 @@ async function createServer(config = {}) {
45697
46511
  await engine.storeCurationResult(body.project_id, body.session_id, result, body.project_path);
45698
46512
  logger.logCurationComplete(result.memories.length, result.session_summary);
45699
46513
  logger.logCuratedMemories(result.memories);
46514
+ const sessionNumber = await engine.getSessionNumber(body.project_id, body.project_path);
46515
+ setImmediate(async () => {
46516
+ try {
46517
+ logger.logManagementStart(result.memories.length);
46518
+ const startTime = Date.now();
46519
+ const managementResult = await manager.manageWithCLI(body.project_id, sessionNumber, result);
46520
+ logger.logManagementComplete({
46521
+ success: managementResult.success,
46522
+ superseded: managementResult.superseded || undefined,
46523
+ resolved: managementResult.resolved || undefined,
46524
+ linked: managementResult.linked || undefined,
46525
+ primerUpdated: managementResult.primerUpdated,
46526
+ summary: managementResult.summary.slice(0, 100),
46527
+ error: managementResult.error
46528
+ });
46529
+ await engine.storeManagementLog({
46530
+ projectId: body.project_id,
46531
+ sessionNumber,
46532
+ memoriesProcessed: result.memories.length,
46533
+ supersededCount: managementResult.superseded,
46534
+ resolvedCount: managementResult.resolved,
46535
+ linkedCount: managementResult.linked,
46536
+ primerUpdated: managementResult.primerUpdated,
46537
+ success: managementResult.success,
46538
+ durationMs: Date.now() - startTime,
46539
+ summary: managementResult.summary,
46540
+ error: managementResult.error
46541
+ });
46542
+ } catch (error) {
46543
+ logger.error(`Management failed: ${error}`);
46544
+ }
46545
+ });
45700
46546
  } else {
45701
46547
  logger.logCurationComplete(0);
45702
46548
  }
@@ -45730,6 +46576,7 @@ async function createServer(config = {}) {
45730
46576
  server,
45731
46577
  engine,
45732
46578
  curator,
46579
+ manager,
45733
46580
  embeddings,
45734
46581
  stop: () => server.stop()
45735
46582
  };
@@ -45739,12 +46586,14 @@ if (__require.main == __require.module) {
45739
46586
  const host = process.env.MEMORY_HOST ?? "localhost";
45740
46587
  const storageMode = process.env.MEMORY_STORAGE_MODE ?? "central";
45741
46588
  const apiKey = process.env.ANTHROPIC_API_KEY;
45742
- await createServer({
45743
- port,
45744
- host,
45745
- storageMode,
45746
- curator: { apiKey }
45747
- });
46589
+ (async () => {
46590
+ await createServer({
46591
+ port,
46592
+ host,
46593
+ storageMode,
46594
+ curator: { apiKey }
46595
+ });
46596
+ })();
45748
46597
  }
45749
46598
  export {
45750
46599
  createServer