@mnemonic-ai/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/chunk-5Z46NSNR.js +228 -0
  2. package/dist/chunk-5Z46NSNR.js.map +1 -0
  3. package/dist/chunk-CZDK53NR.js +24 -0
  4. package/dist/chunk-CZDK53NR.js.map +1 -0
  5. package/dist/chunk-L7SCUMC3.js +53 -0
  6. package/dist/chunk-L7SCUMC3.js.map +1 -0
  7. package/dist/chunk-M3IZJTMM.js +474 -0
  8. package/dist/chunk-M3IZJTMM.js.map +1 -0
  9. package/dist/chunk-NA7L5FQN.js +1581 -0
  10. package/dist/chunk-NA7L5FQN.js.map +1 -0
  11. package/dist/chunk-OEEEWS2M.js +375 -0
  12. package/dist/chunk-OEEEWS2M.js.map +1 -0
  13. package/dist/chunk-YZW6DYUY.js +46 -0
  14. package/dist/chunk-YZW6DYUY.js.map +1 -0
  15. package/dist/cli/main.cjs +1827 -0
  16. package/dist/cli/main.cjs.map +1 -0
  17. package/dist/cli/main.d.cts +1 -0
  18. package/dist/cli/main.d.ts +1 -0
  19. package/dist/cli/main.js +84 -0
  20. package/dist/cli/main.js.map +1 -0
  21. package/dist/client-b2Xhkqdl.d.cts +409 -0
  22. package/dist/client-b2Xhkqdl.d.ts +409 -0
  23. package/dist/index.cjs +2547 -0
  24. package/dist/index.cjs.map +1 -0
  25. package/dist/index.d.cts +309 -0
  26. package/dist/index.d.ts +309 -0
  27. package/dist/index.js +160 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/local-MYLINANE.js +7 -0
  30. package/dist/local-MYLINANE.js.map +1 -0
  31. package/dist/mcp/main.cjs +2775 -0
  32. package/dist/mcp/main.cjs.map +1 -0
  33. package/dist/mcp/main.d.cts +1 -0
  34. package/dist/mcp/main.d.ts +1 -0
  35. package/dist/mcp/main.js +31 -0
  36. package/dist/mcp/main.js.map +1 -0
  37. package/dist/mcp/server.cjs +2765 -0
  38. package/dist/mcp/server.cjs.map +1 -0
  39. package/dist/mcp/server.d.cts +23 -0
  40. package/dist/mcp/server.d.ts +23 -0
  41. package/dist/mcp/server.js +12 -0
  42. package/dist/mcp/server.js.map +1 -0
  43. package/dist/openai-GDIC3YVT.js +7 -0
  44. package/dist/openai-GDIC3YVT.js.map +1 -0
  45. package/dist/postgres-GQ6DZDBW.js +8 -0
  46. package/dist/postgres-GQ6DZDBW.js.map +1 -0
  47. package/package.json +117 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/config.ts","../src/core/classifier.ts","../src/core/scorer.ts","../src/core/linker.ts","../src/core/assembler.ts","../src/core/promotion.ts","../src/core/salience.ts","../src/consolidation/engine.ts","../src/stores/sync-adapter.ts","../src/stores/sqlite.ts","../src/client.ts"],"sourcesContent":["/**\n * Centralised configuration for all Mnemonic tunables.\n */\n\nimport type { Memory } from \"./memory.js\";\n\n// ── Scorer ────────────────────────────────────────────────────────────\n\nexport interface ScorerConfig {\n weightRecency: number;\n weightFrequency: number;\n weightLinks: number;\n weightBase: number;\n frequencyLogCap: number;\n linkSaturation: number;\n supersessionPenalty: number;\n contradictionPenalty: number;\n consolidationPenalty: number;\n tierBaseScores: Record<string, number>;\n}\n\nexport function createDefaultScorerConfig(): ScorerConfig {\n return {\n weightRecency: 0.4,\n weightFrequency: 0.25,\n weightLinks: 0.2,\n weightBase: 0.15,\n frequencyLogCap: 5.0,\n linkSaturation: 5.0,\n supersessionPenalty: 0.1,\n contradictionPenalty: 0.5,\n consolidationPenalty: 0.5,\n tierBaseScores: {\n identity: 1.0,\n procedural: 0.9,\n structural: 0.8,\n episodic: 0.5,\n transient: 0.2,\n },\n };\n}\n\n// ── Classifier ────────────────────────────────────────────────────────\n\nexport interface ClassifierConfig {\n extraPatterns: Record<string, string[]>;\n episodicMinWords: number;\n customClassifier: ((content: string, source: string, actor: string) => string) | null;\n}\n\nexport function createDefaultClassifierConfig(): ClassifierConfig {\n return {\n extraPatterns: {},\n episodicMinWords: 10,\n customClassifier: null,\n };\n}\n\n// ── Linker ────────────────────────────────────────────────────────────\n\nexport interface LinkerConfig {\n similarityThreshold: number;\n maxLinks: number;\n keywordPenalty: number;\n contradictionThreshold: number;\n elaborationThreshold: number;\n supersessionThreshold: number;\n negationWords: Set<string>;\n customRelationFn: ((a: Memory, b: Memory, similarity: number) => string) | null;\n}\n\nexport function createDefaultLinkerConfig(): LinkerConfig {\n return {\n similarityThreshold: 0.65,\n maxLinks: 10,\n keywordPenalty: 0.8,\n contradictionThreshold: 0.7,\n elaborationThreshold: 0.85,\n supersessionThreshold: 0.8,\n negationWords: new Set([\n \"not\", \"never\", \"don't\", \"doesn't\", \"isn't\", \"aren't\", \"won't\", \"no\",\n ]),\n customRelationFn: null,\n };\n}\n\n// ── Assembler ─────────────────────────────────────────────────────────\n\nexport type SortOrder =\n | \"chronological\"\n | \"importance\"\n | \"relevance\"\n | ((a: Memory, b: Memory) => number);\n\nexport interface AssemblerConfig {\n defaultMaxTokens: number;\n diversityStrength: number;\n sortOrder: SortOrder;\n minRelevance: number;\n}\n\nexport function createDefaultAssemblerConfig(): AssemblerConfig {\n return {\n defaultMaxTokens: 3000,\n diversityStrength: 0.3,\n sortOrder: \"chronological\",\n minRelevance: 0.25,\n };\n}\n\n// ── Consolidation ─────────────────────────────────────────────────────\n\nexport interface ConsolidationConfig {\n minClusterSize: number;\n similarityThreshold: number;\n maxContentLength: number;\n prefix: string;\n sourceName: string;\n actorName: string;\n /**\n * Custom summary function replacing the default semicolon-join.\n * Receives original memory content strings, returns a summary string.\n * May be sync or async. When null/undefined, the default join is used.\n */\n summarizer?: ((contents: string[]) => Promise<string> | string) | null;\n /** Max candidates for brute-force pairwise similarity (SQLite/default). */\n maxCandidates: number;\n /** Max nearest neighbors per candidate in LATERAL/vector index (Postgres/Neo4j). */\n maxNeighborsPerCandidate: number;\n}\n\nexport function createDefaultConsolidationConfig(): ConsolidationConfig {\n return {\n minClusterSize: 3,\n similarityThreshold: 0.7,\n maxContentLength: 2000,\n prefix: \"[Consolidated]\",\n sourceName: \"consolidation\",\n actorName: \"system\",\n maxCandidates: 1000,\n maxNeighborsPerCandidate: 50,\n };\n}\n\n// ── Promotion ─────────────────────────────────────────────────────────\n\nexport interface PromotionConfig {\n transientToEpisodicAccesses: number;\n episodicToStructuralAccesses: number;\n structuralToIdentityAccesses: number;\n proceduralToIdentityAccesses: number;\n demotionImportanceThreshold: number;\n}\n\nexport function createDefaultPromotionConfig(): PromotionConfig {\n return {\n transientToEpisodicAccesses: 2,\n episodicToStructuralAccesses: 5,\n structuralToIdentityAccesses: 15,\n proceduralToIdentityAccesses: 25,\n demotionImportanceThreshold: 0.1,\n };\n}\n\n// ── Salience ──────────────────────────────────────────────────────────\n\nexport class SalienceSignal {\n readonly name: string;\n readonly patterns: string[];\n readonly boost: number;\n private _compiled: RegExp[];\n\n constructor(name: string, patterns: string[], boost: number) {\n this.name = name;\n this.patterns = patterns;\n this.boost = boost;\n this._compiled = patterns.map((p) => new RegExp(p, \"i\"));\n }\n\n scan(text: string): boolean {\n return this._compiled.some((re) => re.test(text));\n }\n}\n\nexport const BUILTIN_SALIENCE_SIGNALS: SalienceSignal[] = [\n new SalienceSignal(\"error\", [\n \"\\\\b(?:error|exception|traceback|stack\\\\s*trace|segfault|panic|crash)\\\\b\",\n \"\\\\b(?:failed|failure|broken|bug|regression)\\\\b\",\n \"\\\\b(?:404|500|502|503|ECONNREFUSED|OOM|timeout)\\\\b\",\n ], 0.15),\n new SalienceSignal(\"urgency\", [\n \"\\\\b(?:urgent|critical|blocker|p0|p1|sev[- ]?[01]|outage|incident)\\\\b\",\n \"\\\\b(?:ASAP|immediately|right now|emergency)\\\\b\",\n \"\\\\b(?:production is down|prod is down|site is down)\\\\b\",\n ], 0.25),\n new SalienceSignal(\"correction\", [\n \"\\\\b(?:actually|correction|i was wrong|that's wrong|that's not right)\\\\b\",\n \"\\\\b(?:let me correct|i meant|i misspoke|sorry,? i meant)\\\\b\",\n \"\\\\b(?:no,? (?:it's|it is|that's|that is)|wait,? (?:no|actually))\\\\b\",\n ], 0.20),\n new SalienceSignal(\"decision\", [\n \"\\\\b(?:we've decided|final decision|going with|approved|sign[- ]?off)\\\\b\",\n \"\\\\b(?:agreement|consensus|resolved to|committed to)\\\\b\",\n \"\\\\b(?:from now on|henceforth|going forward)\\\\b\",\n ], 0.15),\n new SalienceSignal(\"frustration\", [\n \"\\\\b(?:i(?:'ve| have) told you|already said|keep telling you)\\\\b\",\n \"\\\\b(?:again\\\\?|how many times|stop (?:doing|suggesting))\\\\b\",\n \"\\\\b(?:this is (?:wrong|bad|terrible|awful)|doesn't work)\\\\b\",\n ], 0.20),\n];\n\nexport interface SalienceConfig {\n enabled: boolean;\n maxBoost: number;\n signals: SalienceSignal[];\n}\n\nexport function createDefaultSalienceConfig(): SalienceConfig {\n return {\n enabled: true,\n maxBoost: 0.4,\n signals: [...BUILTIN_SALIENCE_SIGNALS],\n };\n}\n\n// ── Tier Definition ───────────────────────────────────────────────────\n\nexport interface TierDefinition {\n name: string;\n defaultHalfLifeDays: number;\n description: string;\n}\n\nexport const BUILTIN_TIERS: TierDefinition[] = [\n { name: \"identity\", defaultHalfLifeDays: 3650, description: \"Name, role, company, tech stack — near-permanent\" },\n { name: \"procedural\", defaultHalfLifeDays: 365, description: \"Learned workflows, multi-step procedures, how-to knowledge\" },\n { name: \"structural\", defaultHalfLifeDays: 180, description: \"Architecture decisions, preferences, constraints\" },\n { name: \"episodic\", defaultHalfLifeDays: 30, description: \"Specific conversations, tasks completed\" },\n { name: \"transient\", defaultHalfLifeDays: 7, description: \"One-off questions, small talk\" },\n];\n\n// ── Master Config ─────────────────────────────────────────────────────\n\nexport class MnemonicConfig {\n scorer: ScorerConfig;\n classifier: ClassifierConfig;\n linker: LinkerConfig;\n assembler: AssemblerConfig;\n consolidation: ConsolidationConfig;\n promotion: PromotionConfig;\n salience: SalienceConfig;\n charsPerToken: number;\n defaultTier: string;\n embeddingSearchLimit: number;\n private _tiers: Map<string, TierDefinition>;\n\n constructor(overrides?: Partial<{\n scorer: Partial<ScorerConfig>;\n classifier: Partial<ClassifierConfig>;\n linker: Partial<LinkerConfig>;\n assembler: Partial<AssemblerConfig>;\n consolidation: Partial<ConsolidationConfig>;\n promotion: Partial<PromotionConfig>;\n salience: Partial<SalienceConfig>;\n charsPerToken: number;\n defaultTier: string;\n embeddingSearchLimit: number;\n }>) {\n this.scorer = { ...createDefaultScorerConfig(), ...overrides?.scorer };\n this.classifier = { ...createDefaultClassifierConfig(), ...overrides?.classifier };\n this.linker = { ...createDefaultLinkerConfig(), ...overrides?.linker };\n this.assembler = { ...createDefaultAssemblerConfig(), ...overrides?.assembler };\n this.consolidation = { ...createDefaultConsolidationConfig(), ...overrides?.consolidation };\n this.promotion = { ...createDefaultPromotionConfig(), ...overrides?.promotion };\n this.salience = { ...createDefaultSalienceConfig(), ...overrides?.salience };\n this.charsPerToken = overrides?.charsPerToken ?? 4.0;\n this.defaultTier = overrides?.defaultTier ?? \"episodic\";\n this.embeddingSearchLimit = overrides?.embeddingSearchLimit ?? 100;\n\n if (this.consolidation.maxCandidates < 1) {\n throw new Error(`maxCandidates must be >= 1, got ${this.consolidation.maxCandidates}`);\n }\n if (this.consolidation.maxNeighborsPerCandidate < 1) {\n throw new Error(\n `maxNeighborsPerCandidate must be >= 1, got ${this.consolidation.maxNeighborsPerCandidate}`,\n );\n }\n\n this._tiers = new Map();\n for (const td of BUILTIN_TIERS) {\n this._tiers.set(td.name, td);\n }\n }\n\n registerTier(tier: TierDefinition): void {\n this._tiers.set(tier.name, tier);\n if (!(tier.name in this.scorer.tierBaseScores)) {\n this.scorer.tierBaseScores[tier.name] = 0.5;\n }\n }\n\n getTier(name: string): TierDefinition {\n const td = this._tiers.get(name);\n if (!td) throw new Error(`Unknown tier: '${name}'`);\n return td;\n }\n\n tierNames(): string[] {\n return [...this._tiers.keys()];\n }\n\n halfLifeDays(tierName: string): number {\n return this.getTier(tierName).defaultHalfLifeDays;\n }\n}\n","/**\n * Tier classifier with configurable patterns and pluggable custom logic.\n */\n\nimport { MnemonicConfig, type ClassifierConfig } from \"./config.js\";\n\n// ── Default pattern sets (compiled once at module load) ───────────────\n\nconst IDENTITY_PATTERNS = [\n /\\bmy name is\\b/i,\n /\\bi(?:'m| am) (?:a |an )?(?:software|data|ml|backend|frontend|devops|platform)\\b/i,\n /\\bi work (?:at|for)\\b/i,\n /\\bmy (?:role|title|position) is\\b/i,\n /\\bour (?:tech |technology )?stack (?:is|includes)\\b/i,\n /\\bi (?:use|prefer|always use)\\b.+(?:language|framework|editor|ide|os)\\b/i,\n];\n\nconst PROCEDURAL_PATTERNS = [\n /\\b(?:step\\s+\\d|first|then|next|finally|afterwards)\\b.*\\b(?:step|run|execute|do|click|open|type|enter)\\b/i,\n /\\bto\\s+(?:do|deploy|set up|configure|install|build|run|create|fix)\\b.+\\b(?:first|then|after|before|finally)\\b/i,\n /\\bworkflow\\b.*\\b(?:is|goes|looks like|involves)\\b/i,\n /\\bprocedure\\b.*\\b(?:is|for|to)\\b/i,\n /\\bwhen(?:ever)?\\b.+\\b(?:always|you should|we|i) (?:run|do|execute|call|use)\\b/i,\n /\\brecipe\\b.*\\bfor\\b/i,\n /\\brunbook\\b/i,\n];\n\nconst STRUCTURAL_PATTERNS = [\n /\\bwe (?:decided|chose|agreed) to\\b/i,\n /\\barchitectur(?:e|al)\\b/i,\n /\\bconstraint\\b/i,\n /\\brequirement\\b/i,\n /\\bprefer(?:s|ence)?\\b.+(?:over|instead|rather)\\b/i,\n /\\balways\\b.+\\b(?:use|deploy|run)\\b/i,\n /\\bnever\\b.+\\b(?:use|deploy|run)\\b/i,\n /\\bstandard(?:s|ise|ize)?\\b/i,\n /\\bconvention\\b/i,\n];\n\nconst TRANSIENT_PATTERNS = [\n /\\b(?:hey|hi|hello|thanks|thank you|cheers|bye|goodbye)\\b/i,\n /\\bwhat(?:'s| is) the (?:time|date|weather)\\b/i,\n /\\bjust (?:a )?quick\\b/i,\n /\\bnever ?mind\\b/i,\n];\n\nconst COMPILED_DEFAULTS: Array<[string, RegExp[]]> = [\n [\"identity\", IDENTITY_PATTERNS],\n [\"procedural\", PROCEDURAL_PATTERNS],\n [\"structural\", STRUCTURAL_PATTERNS],\n [\"transient\", TRANSIENT_PATTERNS],\n];\n\nfunction buildTierPatterns(cfg: ClassifierConfig): Array<[string, RegExp[]]> {\n if (Object.keys(cfg.extraPatterns).length === 0) {\n return COMPILED_DEFAULTS;\n }\n return COMPILED_DEFAULTS.map(([name, compiled]) => {\n const extra = (cfg.extraPatterns[name] ?? []).map((p) => new RegExp(p, \"i\"));\n return [name, [...compiled, ...extra]];\n });\n}\n\n/** Return the most appropriate tier name for the given content. */\nexport function classify(\n content: string,\n options?: {\n source?: string;\n actor?: string;\n config?: MnemonicConfig;\n },\n): string {\n const config = options?.config ?? new MnemonicConfig();\n const cfg = config.classifier;\n const actor = options?.actor ?? \"\";\n\n if (cfg.customClassifier) {\n return cfg.customClassifier(content, options?.source ?? \"\", actor);\n }\n\n for (const [tierName, patterns] of buildTierPatterns(cfg)) {\n for (const pat of patterns) {\n if (pat.test(content)) {\n return tierName;\n }\n }\n }\n\n if (actor === \"user\" && content.split(/\\s+/).length > cfg.episodicMinWords) {\n return \"episodic\";\n }\n\n return config.defaultTier;\n}\n","/**\n * Dynamic importance scoring engine.\n */\n\nimport { MnemonicConfig } from \"./config.js\";\nimport type { Memory } from \"./memory.js\";\n\nfunction recencyFactor(memory: Memory, halfLifeDays: number): number {\n const now = Date.now();\n const elapsedDays = Math.max(0, (now - memory.lastAccessedAt.getTime()) / 86_400_000);\n return Math.pow(0.5, elapsedDays / halfLifeDays);\n}\n\nfunction frequencyFactor(memory: Memory, logCap: number): number {\n if (logCap <= 0) return 1.0;\n return Math.min(1.0, Math.log2(1 + memory.accessCount) / logCap);\n}\n\nfunction linkFactor(memory: Memory, saturation: number): number {\n return Math.min(1.0, memory.linkedIds.length / saturation);\n}\n\n/** Compute the current importance score for a memory. */\nexport function score(memory: Memory, config?: MnemonicConfig): number {\n const cfg = config ?? new MnemonicConfig();\n const sc = cfg.scorer;\n\n const tierName = memory.tierName;\n let halfLife: number;\n try {\n halfLife = cfg.halfLifeDays(tierName);\n } catch {\n halfLife = 30;\n }\n\n const base = sc.tierBaseScores[tierName] ?? 0.5;\n\n const composite =\n sc.weightRecency * recencyFactor(memory, halfLife) +\n sc.weightFrequency * frequencyFactor(memory, sc.frequencyLogCap) +\n sc.weightLinks * linkFactor(memory, sc.linkSaturation) +\n sc.weightBase * base;\n\n const boost = (memory.metadata[\"boost\"] as number) ?? 0;\n let result = Math.max(0, composite + boost);\n\n if (memory.supersededBy != null) {\n result *= Math.min(1.0, Math.max(0.0, sc.supersessionPenalty));\n }\n\n if (memory.supersededBy == null && memory.contradictedBy != null) {\n result *= Math.min(1.0, Math.max(0.0, sc.contradictionPenalty));\n }\n\n // Consolidated originals are deprioritised — the structural summary\n // should win in general recall.\n if (memory.metadata[\"consolidated_into\"] != null) {\n result *= Math.min(1.0, Math.max(0.0, sc.consolidationPenalty));\n }\n\n return result;\n}\n","/**\n * Relationship detection between memories.\n */\n\nimport { MnemonicConfig, type LinkerConfig } from \"./config.js\";\nimport { Memory, type MemoryEdge, createEdge } from \"./memory.js\";\nimport { cosineSimilarityVector } from \"./utils.js\";\n\n// Matches numbers with optional decimal/thousands separators. Does NOT\n// consume a trailing unit suffix (MB, ms, GB, …) — this lets the regex\n// fire on attached-unit patterns like \"10MB\" or \"100ms\" where a trailing\n// \\b would fail (no word-boundary between digit and letter).\nconst NUMBER_RE = /\\b\\d+(?:[.,]\\d+)*/g;\nconst CORRECTION_RE =\n /\\b(?:correction|actually|i was wrong|that was wrong|that's wrong|that's not right)\\b|\\b(?:that isn't right|that isn't correct)\\b|\\b(?:let me correct|i meant|i misspoke|sorry,? i meant)\\b|\\b(?:no,? (?:it's|it is|that's|that is)|wait,? (?:no|actually))\\b|\\b(?:disregard|ignore what i said|scratch that|on second thought)\\b/i;\n\nexport function keywordOverlap(a: string, b: string): number {\n const sa = new Set(a.toLowerCase().split(/\\s+/));\n const sb = new Set(b.toLowerCase().split(/\\s+/));\n if (sa.size === 0 || sb.size === 0) return 0;\n\n let intersection = 0;\n for (const word of sa) {\n if (sb.has(word)) intersection++;\n }\n const union = new Set([...sa, ...sb]).size;\n return intersection / union;\n}\n\nfunction extractNumbers(text: string): Set<string> {\n return new Set(text.match(NUMBER_RE) ?? []);\n}\n\nexport function hasNumberDisagreement(a: string, b: string): boolean {\n const aNums = extractNumbers(a);\n const bNums = extractNumbers(b);\n if (aNums.size === 0 || bNums.size === 0) return false;\n if (aNums.size !== bNums.size) return true;\n for (const n of aNums) {\n if (!bNums.has(n)) return true;\n }\n return false;\n}\n\nexport function hasCorrectionSignal(text: string): boolean {\n return CORRECTION_RE.test(text);\n}\n\nfunction inferRelation(\n a: Memory,\n b: Memory,\n similarity: number,\n cfg: LinkerConfig,\n): string {\n if (cfg.customRelationFn) {\n return cfg.customRelationFn(a, b, similarity);\n }\n\n const aWords = new Set(a.content.toLowerCase().split(/\\s+/));\n const bWords = new Set(b.content.toLowerCase().split(/\\s+/));\n\n const hasNegation =\n [...aWords].some((w) => cfg.negationWords.has(w)) !==\n [...bWords].some((w) => cfg.negationWords.has(w));\n const hasNumbers = hasNumberDisagreement(a.content, b.content);\n const hasCorrection =\n hasCorrectionSignal(a.content) || hasCorrectionSignal(b.content);\n\n const hasContradiction =\n (hasNegation || hasNumbers || hasCorrection) &&\n similarity > cfg.contradictionThreshold;\n\n // Number disagreement and correction language are strong evidence of\n // supersession even at moderate similarity levels — both signal that\n // the speaker is explicitly replacing prior information.\n if (hasContradiction && a.createdAt > b.createdAt) {\n if (hasNumbers || hasCorrection || similarity > cfg.supersessionThreshold) {\n return \"supersedes\";\n }\n }\n\n if (hasContradiction) return \"contradicts\";\n if (similarity > cfg.elaborationThreshold) return \"elaborates\";\n return \"related_to\";\n}\n\n/** Identify edges from newMemory to the most related existing memories. */\nexport function findLinks(\n newMemory: Memory,\n existing: Memory[],\n options?: {\n config?: MnemonicConfig;\n similarityThreshold?: number;\n maxLinks?: number;\n },\n): MemoryEdge[] {\n const cfg = (options?.config ?? new MnemonicConfig()).linker;\n const threshold = options?.similarityThreshold ?? cfg.similarityThreshold;\n const limit = options?.maxLinks ?? cfg.maxLinks;\n\n const others = existing.filter((m) => m.id !== newMemory.id);\n if (others.length === 0) return [];\n\n const scored: Array<[number, Memory]> = [];\n\n if (newMemory.embedding) {\n const withEmb = others.filter((m) => m.embedding != null);\n const withoutEmb = others.filter((m) => m.embedding == null);\n\n if (withEmb.length > 0) {\n const embList = withEmb.map((m) => m.embedding!);\n const sims = cosineSimilarityVector(newMemory.embedding, embList);\n for (let i = 0; i < withEmb.length; i++) {\n if (sims[i] >= threshold) {\n scored.push([sims[i], withEmb[i]]);\n }\n }\n }\n\n for (const mem of withoutEmb) {\n const sim =\n keywordOverlap(newMemory.content, mem.content) * cfg.keywordPenalty;\n if (sim >= threshold) scored.push([sim, mem]);\n }\n } else {\n for (const mem of others) {\n const sim =\n keywordOverlap(newMemory.content, mem.content) * cfg.keywordPenalty;\n if (sim >= threshold) scored.push([sim, mem]);\n }\n }\n\n scored.sort((a, b) => b[0] - a[0]);\n\n return scored.slice(0, limit).map(([sim, mem]) => {\n const relation = inferRelation(newMemory, mem, sim, cfg);\n return createEdge(newMemory.id, mem.id, relation, sim);\n });\n}\n","/**\n * Context window assembly — greedy budget-filling with diversity penalty.\n *\n * Uses pre-computed similarity matrices for O(1) diversity lookups.\n */\n\nimport { MnemonicConfig, type SortOrder } from \"./config.js\";\nimport { hasCorrectionSignal, hasNumberDisagreement, keywordOverlap } from \"./linker.js\";\nimport type { Memory } from \"./memory.js\";\nimport { score as scoreMemory } from \"./scorer.js\";\nimport { cosineSimilarityMatrix, cosineSimilarityVector } from \"./utils.js\";\n\nfunction getSortFn(sortOrder: SortOrder): (a: Memory, b: Memory) => number {\n if (typeof sortOrder === \"function\") return sortOrder;\n if (sortOrder === \"importance\") return (a, b) => b.importance - a.importance;\n if (sortOrder === \"relevance\") return () => 0;\n // chronological (default)\n return (a, b) => a.createdAt.getTime() - b.createdAt.getTime();\n}\n\n/** Select and order memories to fill a token budget. */\nexport function assemble(\n _query: string,\n candidates: Memory[],\n options?: {\n queryEmbedding?: number[] | null;\n maxTokens?: number;\n diversityStrength?: number;\n minRelevance?: number;\n config?: MnemonicConfig;\n },\n): Memory[] {\n const config = options?.config ?? new MnemonicConfig();\n const cfg = config.assembler;\n const budget = options?.maxTokens ?? cfg.defaultMaxTokens;\n const divStrength = options?.diversityStrength ?? cfg.diversityStrength;\n const relevanceFloor = options?.minRelevance ?? cfg.minRelevance;\n const qEmbed = options?.queryEmbedding ?? null;\n let n = candidates.length;\n if (n === 0) return [];\n\n // Pre-compute importance scores.\n let importances = new Float64Array(n);\n for (let i = 0; i < n; i++) {\n importances[i] = scoreMemory(candidates[i], config);\n }\n\n // Pre-compute relevance scores — keyword-based for all, embedding override where available.\n let embIndices: number[] = [];\n for (let i = 0; i < n; i++) {\n if (candidates[i].embedding) embIndices.push(i);\n }\n\n let relevances = new Float64Array(n);\n for (let i = 0; i < n; i++) {\n relevances[i] = keywordOverlap(_query, candidates[i].content);\n }\n\n if (qEmbed && embIndices.length > 0) {\n const embList = embIndices.map((i) => candidates[i].embedding!);\n const sims = cosineSimilarityVector(qEmbed, embList);\n for (let pos = 0; pos < embIndices.length; pos++) {\n const idx = embIndices[pos];\n // Keyword overlap can only boost, not reduce embedding score.\n relevances[idx] = Math.max(Math.max(0, sims[pos]), relevances[idx]);\n }\n }\n\n // Filter out candidates below the minimum relevance threshold.\n if (relevanceFloor > 0) {\n const keep: number[] = [];\n for (let i = 0; i < n; i++) {\n if (relevances[i] >= relevanceFloor) keep.push(i);\n }\n if (keep.length < n) {\n const oldToNew = new Map<number, number>();\n keep.forEach((old, idx) => oldToNew.set(old, idx));\n candidates = keep.map((i) => candidates[i]);\n importances = Float64Array.from(keep.map((i) => importances[i]));\n relevances = Float64Array.from(keep.map((i) => relevances[i]));\n embIndices = embIndices.filter((i) => oldToNew.has(i)).map((i) => oldToNew.get(i)!);\n n = candidates.length;\n }\n }\n\n // Pre-compute pairwise similarity matrix for diversity.\n let simMatrix: Float64Array | null = null;\n const idxToPos = new Map<number, number>();\n if (embIndices.length > 0 && divStrength > 0) {\n const embList = embIndices.map((i) => candidates[i].embedding!);\n simMatrix = cosineSimilarityMatrix(embList);\n for (let pos = 0; pos < embIndices.length; pos++) {\n idxToPos.set(embIndices[pos], pos);\n }\n }\n\n const nEmb = embIndices.length;\n\n // Greedy budget-filling with diversity penalty.\n const remaining = Array.from({ length: n }, (_, i) => i);\n const selectedEmbPositions: number[] = [];\n const selectedIndices: number[] = [];\n let budgetLeft = budget;\n\n while (remaining.length > 0 && budgetLeft > 0) {\n let bestRi = -1;\n let bestValue = -1;\n\n for (let ri = 0; ri < remaining.length; ri++) {\n const ci = remaining[ri];\n if (candidates[ci].tokenEstimate > budgetLeft) continue;\n\n let value = relevances[ci] * importances[ci];\n\n // Diversity penalty using pre-computed similarity matrix.\n if (selectedEmbPositions.length > 0 && simMatrix && idxToPos.has(ci)) {\n const pos = idxToPos.get(ci)!;\n let maxSim = 0;\n for (const sp of selectedEmbPositions) {\n const s = simMatrix[pos * nEmb + sp];\n if (s > maxSim) maxSim = s;\n }\n value *= Math.min(1, Math.max(0, 1.0 - divStrength * maxSim));\n }\n\n if (value > bestValue) {\n bestValue = value;\n bestRi = ri;\n }\n }\n\n if (bestRi < 0) break;\n\n const chosenIdx = remaining.splice(bestRi, 1)[0];\n candidates[chosenIdx].touch();\n selectedIndices.push(chosenIdx);\n if (idxToPos.has(chosenIdx)) {\n selectedEmbPositions.push(idxToPos.get(chosenIdx)!);\n }\n budgetLeft -= candidates[chosenIdx].tokenEstimate;\n }\n\n const selected = selectedIndices.map((i) => candidates[i]);\n selected.sort(getSortFn(cfg.sortOrder));\n return selected;\n}\n\n/**\n * Find potential conflicts among assembled memories.\n *\n * Uses two complementary strategies:\n * 1. **Pre-computed relationships** — if a memory's `contradictedBy`\n * field points to another memory in the set, emit a conflict. This\n * catches cases the heuristic scan misses (e.g. procedural negation\n * detected at store time).\n * 2. **Pairwise text analysis** — number disagreements, correction\n * language, and negation-word asymmetry on similar content.\n */\nexport function detectConflicts(\n memories: Memory[],\n config?: MnemonicConfig,\n): Array<[number, number, string]> {\n const cfg = config ?? new MnemonicConfig();\n const negWords = cfg.linker.negationWords;\n const conflicts: Array<[number, number, string]> = [];\n const seenPairs = new Set<string>();\n const n = memories.length;\n\n const pairKey = (a: number, b: number) => `${Math.min(a, b)},${Math.max(a, b)}`;\n\n // Strategy 1: surface pre-computed contradictedBy relationships.\n const idToIdx = new Map<string, number>();\n for (let i = 0; i < n; i++) idToIdx.set(memories[i].id, i);\n\n for (let i = 0; i < n; i++) {\n const mem = memories[i];\n if (mem.contradictedBy && idToIdx.has(mem.contradictedBy)) {\n const j = idToIdx.get(mem.contradictedBy)!;\n const key = pairKey(i, j);\n if (!seenPairs.has(key)) {\n seenPairs.add(key);\n conflicts.push([Math.min(i, j), Math.max(i, j), \"contradicted by newer memory\"]);\n }\n }\n }\n\n // Strategy 2: pairwise text analysis.\n for (let i = 0; i < n; i++) {\n for (let j = i + 1; j < n; j++) {\n const key = pairKey(i, j);\n if (seenPairs.has(key)) continue;\n\n const a = memories[i], b = memories[j];\n const kwSim = keywordOverlap(a.content, b.content);\n\n let embSim = 0;\n if (a.embedding && b.embedding) {\n const sims = cosineSimilarityVector(a.embedding, [b.embedding]);\n embSim = sims[0];\n }\n const maxSim = Math.max(kwSim, embSim);\n if (maxSim < 0.60) continue;\n\n if (hasNumberDisagreement(a.content, b.content)) {\n conflicts.push([i, j, \"numbers differ on similar topic\"]);\n seenPairs.add(key);\n } else if (hasCorrectionSignal(a.content) || hasCorrectionSignal(b.content)) {\n conflicts.push([i, j, \"correction language detected\"]);\n seenPairs.add(key);\n } else if (maxSim > 0.80) {\n const aWords = new Set(a.content.toLowerCase().split(/\\s+/));\n const bWords = new Set(b.content.toLowerCase().split(/\\s+/));\n const aNeg = [...aWords].some((w) => negWords.has(w));\n const bNeg = [...bWords].some((w) => negWords.has(w));\n if (aNeg !== bNeg) {\n conflicts.push([i, j, \"contradictory statements\"]);\n seenPairs.add(key);\n }\n }\n }\n }\n return conflicts;\n}\n\n/** Render assembled memories as a plain-text block. */\nexport function formatContext(\n memories: Memory[],\n header: string = \"Relevant context:\",\n conflicts?: Array<[number, number, string]>,\n): string {\n if (memories.length === 0) return \"\";\n const lines = [header, \"\"];\n for (const mem of memories) {\n lines.push(`- [${mem.tierName}] ${mem.content}`);\n }\n if (conflicts && conflicts.length > 0) {\n lines.push(\"\");\n for (const [idxA, idxB, reason] of conflicts) {\n lines.push(`[!] Potential conflict between items ${idxA + 1} and ${idxB + 1}: ${reason}`);\n }\n }\n return lines.join(\"\\n\");\n}\n","/**\n * Tier promotion and demotion — the memory maturation pipeline.\n *\n * transient → episodic → structural → identity\n * ↑\n * procedural ──┘\n */\n\nimport { MnemonicConfig, type PromotionConfig } from \"./config.js\";\nimport type { Memory } from \"./memory.js\";\nimport { score as scoreMemory } from \"./scorer.js\";\n\n// ── Tier transition table ────────────────────────────────────────────\n\ninterface TierTransition {\n promoteTo: string | null;\n demoteTo: string | null;\n promoteThresholdKey: keyof PromotionConfig | null;\n}\n\nconst TIER_TRANSITIONS: Record<string, TierTransition> = {\n transient: { promoteTo: \"episodic\", demoteTo: null, promoteThresholdKey: \"transientToEpisodicAccesses\" },\n episodic: { promoteTo: \"structural\", demoteTo: \"transient\", promoteThresholdKey: \"episodicToStructuralAccesses\" },\n structural: { promoteTo: \"identity\", demoteTo: \"episodic\", promoteThresholdKey: \"structuralToIdentityAccesses\" },\n procedural: { promoteTo: \"identity\", demoteTo: \"structural\", promoteThresholdKey: \"proceduralToIdentityAccesses\" },\n identity: { promoteTo: null, demoteTo: \"structural\", promoteThresholdKey: null },\n};\n\nexport interface PromotionResult {\n memoryId: string;\n oldTier: string;\n newTier: string;\n reason: string;\n}\n\n/** Identify memories that qualify for tier promotion. */\nexport function checkPromotions(\n memories: Memory[],\n config?: MnemonicConfig,\n): PromotionResult[] {\n const cfg = (config ?? new MnemonicConfig()).promotion;\n const results: PromotionResult[] = [];\n\n for (const mem of memories) {\n const transition = TIER_TRANSITIONS[mem.tierName];\n if (!transition?.promoteTo || !transition.promoteThresholdKey) continue;\n\n const threshold = cfg[transition.promoteThresholdKey] as number;\n if (mem.accessCount >= threshold) {\n results.push({\n memoryId: mem.id,\n oldTier: mem.tierName,\n newTier: transition.promoteTo,\n reason: `access_count (${mem.accessCount}) >= ${threshold}`,\n });\n }\n }\n\n return results;\n}\n\n/** Identify memories that qualify for tier demotion. */\nexport function checkDemotions(\n memories: Memory[],\n config?: MnemonicConfig,\n): PromotionResult[] {\n const fullCfg = config ?? new MnemonicConfig();\n const cfg = fullCfg.promotion;\n const results: PromotionResult[] = [];\n\n for (const mem of memories) {\n if (mem.supersededBy != null) continue;\n\n const transition = TIER_TRANSITIONS[mem.tierName];\n if (!transition?.demoteTo) continue;\n\n const importance = scoreMemory(mem, fullCfg);\n if (importance < cfg.demotionImportanceThreshold) {\n results.push({\n memoryId: mem.id,\n oldTier: mem.tierName,\n newTier: transition.demoteTo,\n reason: `importance (${importance.toFixed(4)}) < ${cfg.demotionImportanceThreshold}`,\n });\n }\n }\n\n return results;\n}\n\n/** Change a memory's tier in-place, recording history. */\nexport function applyTierChange(memory: Memory, newTier: string): void {\n const oldTier = memory.tierName;\n const history = (memory.metadata[\"previous_tiers\"] as string[]) ?? [];\n history.push(oldTier);\n memory.metadata[\"previous_tiers\"] = history;\n memory.tier = newTier;\n}\n","/**\n * Automatic salience detection — the amygdala of the memory system.\n */\n\nimport {\n type SalienceConfig,\n createDefaultSalienceConfig,\n} from \"./config.js\";\n\nexport interface SalienceResult {\n boost: number;\n signals: string[];\n}\n\n/** Scan content for salience signals. */\nexport function detectSalience(\n content: string,\n config?: SalienceConfig,\n): SalienceResult {\n const cfg = config ?? createDefaultSalienceConfig();\n if (!cfg.enabled) {\n return { boost: 0, signals: [] };\n }\n\n let totalBoost = 0;\n const fired: string[] = [];\n\n for (const signal of cfg.signals) {\n if (signal.scan(content)) {\n totalBoost += signal.boost;\n fired.push(signal.name);\n }\n }\n\n return {\n boost: Math.min(totalBoost, cfg.maxBoost),\n signals: fired,\n };\n}\n","/**\n * Memory consolidation — merging episodic memories into semantic summaries.\n */\n\nimport { MnemonicConfig } from \"../core/config.js\";\nimport { keywordOverlap } from \"../core/linker.js\";\nimport { Memory, type SimilarPair } from \"../core/memory.js\";\nimport { cosineSimilarityMatrix } from \"../core/utils.js\";\n\n/** Error names that indicate transient LLM failures — should propagate, not fall back. */\nexport const TRANSIENT_ERRORS = new Set([\n \"RateLimitError\",\n \"APITimeoutError\",\n \"APIConnectionTimeoutError\", // OpenAI Node SDK timeout subclass\n \"APIConnectionError\",\n \"InternalServerError\",\n]);\n\n/**\n * Group episodic memories that overlap enough to consolidate.\n *\n * When `pairs` is provided, union-find runs directly on the sparse pairs\n * (no N×N matrix). When omitted, falls back to brute-force matrix.\n */\nexport function findConsolidationCandidates(\n memories: Memory[],\n config?: MnemonicConfig,\n pairs?: SimilarPair[],\n): Memory[][] {\n const cfg = (config ?? new MnemonicConfig()).consolidation;\n\n const episodic = memories.filter(\n (m) => m.tierName === \"episodic\" && m.embedding != null,\n );\n if (episodic.length < cfg.minClusterSize) return [];\n\n if (pairs != null) {\n return clusterFromPairs(episodic, pairs, cfg.minClusterSize);\n }\n return clusterFromMatrix(episodic, cfg.similarityThreshold, cfg.minClusterSize);\n}\n\n/** Single-linkage clustering via union-find on integer-indexed edges. */\nfunction unionFindClusters(\n items: Memory[],\n edges: [number, number][],\n minClusterSize: number,\n): Memory[][] {\n const n = items.length;\n const parent = Array.from({ length: n }, (_, i) => i);\n\n function find(x: number): number {\n while (parent[x] !== x) {\n parent[x] = parent[parent[x]];\n x = parent[x];\n }\n return x;\n }\n\n for (const [a, b] of edges) {\n const ra = find(a);\n const rb = find(b);\n if (ra !== rb) parent[ra] = rb;\n }\n\n const clusters = new Map<number, Memory[]>();\n for (let i = 0; i < n; i++) {\n const root = find(i);\n if (!clusters.has(root)) clusters.set(root, []);\n clusters.get(root)!.push(items[i]);\n }\n\n return [...clusters.values()].filter((c) => c.length >= minClusterSize);\n}\n\nfunction clusterFromPairs(\n episodic: Memory[],\n pairs: SimilarPair[],\n minClusterSize: number,\n): Memory[][] {\n const idToIdx = new Map<string, number>();\n for (let i = 0; i < episodic.length; i++) {\n idToIdx.set(episodic[i].id, i);\n }\n const edges: [number, number][] = [];\n for (const p of pairs) {\n const ia = idToIdx.get(p.idA);\n const ib = idToIdx.get(p.idB);\n if (ia != null && ib != null) {\n edges.push([ia, ib]);\n }\n }\n return unionFindClusters(episodic, edges, minClusterSize);\n}\n\nfunction clusterFromMatrix(\n episodic: Memory[],\n similarityThreshold: number,\n minClusterSize: number,\n): Memory[][] {\n const n = episodic.length;\n const simMatrix = cosineSimilarityMatrix(episodic.map((m) => m.embedding!));\n const edges: [number, number][] = [];\n for (let i = 0; i < n; i++) {\n for (let j = i + 1; j < n; j++) {\n if (simMatrix[i * n + j] >= similarityThreshold) {\n edges.push([i, j]);\n }\n }\n }\n return unionFindClusters(episodic, edges, minClusterSize);\n}\n\nfunction defaultJoin(cluster: Memory[], maxLength: number): string {\n // Sort newest first.\n const sorted = [...cluster].sort(\n (a, b) => b.createdAt.getTime() - a.createdAt.getTime(),\n );\n\n const unique: string[] = [];\n for (const mem of sorted) {\n if (unique.some((prev) => keywordOverlap(mem.content, prev) > 0.80)) continue;\n unique.push(mem.content);\n }\n\n const header = `(${cluster.length} memories, ${unique.length} unique)`;\n let combined = header + \"\\n\" + unique.join(\"\\n\");\n if (combined.length > maxLength) {\n combined = combined.slice(0, maxLength - 3) + \"...\";\n }\n return combined;\n}\n\n/** Create a single structural memory summarising a cluster. */\nexport async function mergeCluster(\n cluster: Memory[],\n config?: MnemonicConfig,\n): Promise<Memory> {\n const cfg = (config ?? new MnemonicConfig()).consolidation;\n\n let combined: string;\n if (cfg.summarizer != null) {\n try {\n combined = (await cfg.summarizer(cluster.map((m) => m.content))).trim();\n if (!combined) {\n throw new Error(\"Summarizer returned empty content\");\n }\n } catch (err: unknown) {\n // Transient errors (rate limits, timeouts, network) should propagate\n // so the consolidation job can be retried — falling back would\n // permanently degrade the summary into a lossy join.\n const errName = err instanceof Error ? err.constructor.name : \"\";\n if (TRANSIENT_ERRORS.has(errName)) {\n throw err;\n }\n console.warn(`Summarizer failed permanently with ${errName}; falling back to default join`);\n combined = defaultJoin(cluster, cfg.maxContentLength);\n }\n // Safety cap: prevent unbounded summaries from consuming the\n // entire token budget during recall.\n if (combined.length > cfg.maxContentLength) {\n combined = combined.slice(0, cfg.maxContentLength - 3) + \"...\";\n }\n } else {\n combined = defaultJoin(cluster, cfg.maxContentLength);\n }\n\n const summary = new Memory({\n content: `${cfg.prefix} ${combined}`,\n tier: \"structural\",\n source: cfg.sourceName,\n actor: cfg.actorName,\n metadata: {\n consolidated_from: cluster.map((m) => m.id),\n original_count: cluster.length,\n },\n });\n\n summary.importance = Math.max(...cluster.map((m) => m.importance));\n const linkedSet = new Set(cluster.flatMap((m) => m.linkedIds));\n summary.linkedIds = [...linkedSet];\n\n return summary;\n}\n","/**\n * Adapter that wraps a synchronous BaseStore into an AsyncBaseStore.\n * Uses async functions so thrown errors become rejected promises.\n */\n\nimport type { Memory, MemoryEdge, SimilarPair } from \"../core/memory.js\";\nimport type { BaseStore, AgentFilterOptions } from \"./base.js\";\nimport type { AsyncBaseStore } from \"./async-base.js\";\n\n/** Wrap a synchronous BaseStore so it can be used as AsyncBaseStore. */\nexport function syncToAsync(store: BaseStore): AsyncBaseStore {\n return {\n async initialize() { store.initialize(); },\n async close() { store.close(); },\n async save(memory: Memory) { store.save(memory); },\n async get(memoryId: string) { return store.get(memoryId); },\n async listAll(options?: AgentFilterOptions) { return store.listAll(options); },\n async delete(memoryId: string) { store.delete(memoryId); },\n async deleteOlderThan(ageMs: number, tier?: string, options?: AgentFilterOptions) {\n return store.deleteOlderThan(ageMs, tier, options);\n },\n async saveEdge(edge: MemoryEdge) { store.saveEdge(edge); },\n async getEdges(memoryId: string) { return store.getEdges(memoryId); },\n async searchByEmbedding(embedding: number[], limit?: number, options?: AgentFilterOptions) {\n return store.searchByEmbedding(embedding, limit, options);\n },\n async findSimilarPairs(options?: {\n threshold?: number; agentId?: string; tier?: string; maxCandidates?: number;\n }): Promise<SimilarPair[]> {\n return store.findSimilarPairs(options);\n },\n async getMeta(key: string) { return store.getMeta(key); },\n async setMeta(key: string, value: string) { store.setMeta(key, value); },\n };\n}\n","/**\n * SQLite-backed memory store — the zero-config default.\n */\n\nimport Database from \"better-sqlite3\";\nimport type { Database as DatabaseType } from \"better-sqlite3\";\nimport { Memory, type MemoryEdge, type SimilarPair } from \"../core/memory.js\";\nimport { bruteForceCosineSearch, bruteForceSimilarPairs } from \"../core/utils.js\";\nimport type { BaseStore, AgentFilterOptions } from \"./base.js\";\n\nconst SCHEMA = `\nCREATE TABLE IF NOT EXISTS memories (\n id TEXT PRIMARY KEY,\n content TEXT NOT NULL,\n tier TEXT NOT NULL,\n source TEXT NOT NULL DEFAULT 'unknown',\n actor TEXT NOT NULL DEFAULT 'system',\n session_id TEXT,\n created_at TEXT NOT NULL,\n last_accessed TEXT NOT NULL,\n access_count INTEGER NOT NULL DEFAULT 0,\n importance REAL NOT NULL DEFAULT 1.0,\n superseded_by TEXT,\n contradicted_by TEXT,\n embedding TEXT,\n metadata TEXT NOT NULL DEFAULT '{}',\n linked_ids TEXT NOT NULL DEFAULT '[]',\n agent_id TEXT NOT NULL DEFAULT 'default',\n shared INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE IF NOT EXISTS edges (\n source_id TEXT NOT NULL,\n target_id TEXT NOT NULL,\n relation TEXT NOT NULL,\n weight REAL NOT NULL DEFAULT 1.0,\n created_at TEXT NOT NULL,\n PRIMARY KEY (source_id, target_id, relation)\n);\n\nCREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS idx_memories_agent_id ON memories (agent_id);\n`;\n\nexport class SQLiteStore implements BaseStore {\n private _db: DatabaseType;\n\n constructor(path: string = \"mnemonic.db\") {\n this._db = new Database(path);\n this._db.pragma(\"journal_mode = WAL\");\n }\n\n initialize(): void {\n this._db.exec(SCHEMA);\n this._migrate();\n }\n\n close(): void {\n this._db.close();\n }\n\n /** Add missing columns/tables for stores created before multi-agent support. */\n private _migrate(): void {\n const cols = this._db\n .prepare(\"PRAGMA table_info(memories)\")\n .all() as Array<{ name: string }>;\n const colNames = new Set(cols.map((c) => c.name));\n\n if (!colNames.has(\"agent_id\")) {\n this._db.exec(\n \"ALTER TABLE memories ADD COLUMN agent_id TEXT NOT NULL DEFAULT 'default'\",\n );\n this._db.exec(\n \"CREATE INDEX IF NOT EXISTS idx_memories_agent_id ON memories (agent_id)\",\n );\n }\n if (!colNames.has(\"shared\")) {\n this._db.exec(\n \"ALTER TABLE memories ADD COLUMN shared INTEGER NOT NULL DEFAULT 0\",\n );\n }\n if (!colNames.has(\"contradicted_by\")) {\n this._db.exec(\n \"ALTER TABLE memories ADD COLUMN contradicted_by TEXT\",\n );\n this._db.exec(\n \"UPDATE memories SET contradicted_by = json_extract(metadata, '$.contradicted_by') \" +\n \"WHERE contradicted_by IS NULL AND json_extract(metadata, '$.contradicted_by') IS NOT NULL\",\n );\n }\n\n // Ensure meta table exists (for stores created before this feature)\n this._db.exec(\n \"CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)\",\n );\n }\n\n save(memory: Memory): void {\n this._db\n .prepare(\n `INSERT OR REPLACE INTO memories\n (id, content, tier, source, actor, session_id, created_at,\n last_accessed, access_count, importance, superseded_by,\n contradicted_by, embedding, metadata, linked_ids, agent_id, shared)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n memory.id,\n memory.content,\n memory.tierName,\n memory.source,\n memory.actor,\n memory.sessionId,\n memory.createdAt.toISOString(),\n memory.lastAccessedAt.toISOString(),\n memory.accessCount,\n memory.importance,\n memory.supersededBy,\n memory.contradictedBy ?? null,\n memory.embedding ? JSON.stringify(memory.embedding) : null,\n JSON.stringify(memory.metadata),\n JSON.stringify(memory.linkedIds),\n memory.agentId,\n memory.shared ? 1 : 0,\n );\n }\n\n get(memoryId: string): Memory | null {\n const row = this._db\n .prepare(\"SELECT * FROM memories WHERE id = ?\")\n .get(memoryId) as Record<string, unknown> | undefined;\n if (!row) return null;\n return rowToMemory(row);\n }\n\n listAll(options?: AgentFilterOptions): Memory[] {\n const clauses: string[] = [];\n const params: unknown[] = [];\n\n if (options?.agentId) {\n if (options.includeShared === false) {\n clauses.push(\"agent_id = ?\");\n params.push(options.agentId);\n } else {\n clauses.push(\"(agent_id = ? OR shared = 1)\");\n params.push(options.agentId);\n }\n }\n if (options?.tier != null) {\n clauses.push(\"tier = ?\");\n params.push(options.tier);\n }\n\n const where = clauses.length > 0 ? ` WHERE ${clauses.join(\" AND \")}` : \"\";\n let limitClause = \"\";\n if (options?.limit != null) {\n limitClause = \" LIMIT ?\";\n params.push(options.limit);\n }\n const rows = this._db\n .prepare(`SELECT * FROM memories${where}${limitClause}`)\n .all(...params) as Record<string, unknown>[];\n return rows.map(rowToMemory);\n }\n\n delete(memoryId: string): void {\n this._db.transaction(() => {\n this._db.prepare(\"DELETE FROM memories WHERE id = ?\").run(memoryId);\n this._db\n .prepare(\"DELETE FROM edges WHERE source_id = ? OR target_id = ?\")\n .run(memoryId, memoryId);\n })();\n }\n\n deleteOlderThan(\n ageMs: number,\n tier?: string,\n options?: AgentFilterOptions,\n ): number {\n const cutoff = new Date(Date.now() - ageMs).toISOString();\n const conditions = [\"created_at < ?\"];\n const params: unknown[] = [cutoff];\n\n if (tier != null) {\n conditions.push(\"tier = ?\");\n params.push(tier);\n }\n if (options?.agentId) {\n conditions.push(\"agent_id = ?\");\n params.push(options.agentId);\n }\n\n const where = conditions.join(\" AND \");\n\n // Collect IDs first to cascade-delete edges\n const ids = this._db\n .prepare(`SELECT id FROM memories WHERE ${where}`)\n .all(...params) as Array<{ id: string }>;\n\n if (ids.length === 0) return 0;\n\n const idList = ids.map((r) => r.id);\n const placeholders = idList.map(() => \"?\").join(\",\");\n\n const txn = this._db.transaction(() => {\n this._db\n .prepare(\n `DELETE FROM edges WHERE source_id IN (${placeholders}) OR target_id IN (${placeholders})`,\n )\n .run(...idList, ...idList);\n const result = this._db\n .prepare(`DELETE FROM memories WHERE ${where}`)\n .run(...params);\n return result.changes;\n });\n\n return txn();\n }\n\n saveEdge(edge: MemoryEdge): void {\n this._db\n .prepare(\n `INSERT OR REPLACE INTO edges (source_id, target_id, relation, weight, created_at)\n VALUES (?, ?, ?, ?, ?)`,\n )\n .run(\n edge.sourceId,\n edge.targetId,\n edge.relation,\n edge.weight,\n edge.createdAt.toISOString(),\n );\n }\n\n getEdges(memoryId: string): MemoryEdge[] {\n const rows = this._db\n .prepare(\"SELECT * FROM edges WHERE source_id = ? OR target_id = ?\")\n .all(memoryId, memoryId) as Record<string, unknown>[];\n return rows.map((r) => ({\n sourceId: r[\"source_id\"] as string,\n targetId: r[\"target_id\"] as string,\n relation: r[\"relation\"] as string,\n weight: r[\"weight\"] as number,\n createdAt: new Date(r[\"created_at\"] as string),\n }));\n }\n\n searchByEmbedding(\n embedding: number[],\n limit: number = 50,\n options?: AgentFilterOptions,\n ): Memory[] {\n const all = this.listAll(options);\n return bruteForceCosineSearch(all, embedding, limit);\n }\n\n findSimilarPairs(options?: {\n threshold?: number;\n agentId?: string;\n tier?: string;\n maxCandidates?: number;\n maxNeighborsPerCandidate?: number;\n }): SimilarPair[] {\n const maxCandidates = options?.maxCandidates ?? 1000;\n // Don't push limit to listAll — the cap should apply to the embedded\n // subset, not the raw row count (which may include non-embedded rows).\n const memories = this.listAll({\n agentId: options?.agentId,\n includeShared: false,\n tier: options?.tier,\n });\n return bruteForceSimilarPairs(\n memories,\n options?.threshold ?? 0.7,\n maxCandidates,\n );\n }\n\n getMeta(key: string): string | null {\n const row = this._db\n .prepare(\"SELECT value FROM meta WHERE key = ?\")\n .get(key) as { value: string } | undefined;\n return row?.value ?? null;\n }\n\n setMeta(key: string, value: string): void {\n this._db\n .prepare(\"INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)\")\n .run(key, value);\n }\n}\n\nfunction rowToMemory(row: Record<string, unknown>): Memory {\n const embRaw = row[\"embedding\"] as string | null;\n const m = new Memory({\n id: row[\"id\"] as string,\n content: row[\"content\"] as string,\n tier: row[\"tier\"] as string,\n source: row[\"source\"] as string,\n actor: row[\"actor\"] as string,\n sessionId: row[\"session_id\"] as string | null,\n createdAt: new Date(row[\"created_at\"] as string),\n lastAccessedAt: new Date(row[\"last_accessed\"] as string),\n accessCount: row[\"access_count\"] as number,\n importance: row[\"importance\"] as number,\n supersededBy: row[\"superseded_by\"] as string | null,\n embedding: embRaw ? (JSON.parse(embRaw) as number[]) : null,\n metadata: JSON.parse(row[\"metadata\"] as string) as Record<string, unknown>,\n linkedIds: JSON.parse(row[\"linked_ids\"] as string) as string[],\n agentId: (row[\"agent_id\"] as string) ?? \"default\",\n shared: row[\"shared\"] === 1 || row[\"shared\"] === true,\n });\n m.contradictedBy = row[\"contradicted_by\"] as string | null;\n return m;\n}\n","/**\n * Top-level Mnemonic client — the public API surface.\n */\n\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { MnemonicConfig } from \"./core/config.js\";\nimport { classify } from \"./core/classifier.js\";\nimport { score } from \"./core/scorer.js\";\nimport { assemble, detectConflicts, formatContext } from \"./core/assembler.js\";\nimport { findLinks } from \"./core/linker.js\";\nimport { Memory, MemoryTier, createEdge } from \"./core/memory.js\";\nimport {\n checkPromotions,\n checkDemotions,\n applyTierChange,\n} from \"./core/promotion.js\";\nimport { detectSalience } from \"./core/salience.js\";\nimport { parseDuration, parseSqlitePath } from \"./core/utils.js\";\nimport {\n findConsolidationCandidates,\n mergeCluster,\n} from \"./consolidation/engine.js\";\nimport type { BaseEmbedder } from \"./embeddings/base.js\";\nimport type { BaseStore } from \"./stores/base.js\";\nimport type { AsyncBaseStore } from \"./stores/async-base.js\";\nimport { syncToAsync } from \"./stores/sync-adapter.js\";\nimport { SQLiteStore } from \"./stores/sqlite.js\";\n\n// ── Store registry ──────────────────────────────────────────────────────\n// Allows external packages (e.g. mnemonic-platform) to register additional\n// store backends without modifying this module.\n\nexport type StoreFactory = (uri: string, embeddingDim?: number) => BaseStore | AsyncBaseStore | Promise<AsyncBaseStore>;\n\nconst _storeRegistry = new Map<string, StoreFactory>();\n\n/** @internal — iterate registered store factories. */\nexport function _registeredStores(): IterableIterator<[string, StoreFactory]> {\n return _storeRegistry.entries();\n}\n\n/** Strip credentials from a URI for safe error messages. */\nfunction sanitizeUri(uri: string): string {\n try {\n const url = new URL(uri);\n if (url.username || url.password) {\n url.username = \"***\";\n url.password = \"\";\n }\n return url.toString();\n } catch {\n return uri.includes(\"://\") ? uri.split(\"://\")[0] + \"://***\" : uri;\n }\n}\n\nconst SCHEME_RE = /^[a-z][a-z0-9+.-]{0,31}$/;\n\n/**\n * Register a store factory for a URI scheme.\n *\n * The factory receives the full URI and the embedding dimension (if known).\n * Must return a BaseStore or AsyncBaseStore.\n * Throws if `scheme` is already registered (pass `overwrite: true` to replace).\n *\n * @example\n * ```ts\n * registerStore(\"neo4j\", (uri, dim) => new Neo4jStore({ uri, embeddingDim: dim }));\n * new Mnemonic({ store: \"neo4j://localhost\" }); // now works\n * ```\n */\nexport function registerStore(\n scheme: string,\n factory: StoreFactory,\n options?: { overwrite?: boolean },\n): void {\n if (!SCHEME_RE.test(scheme)) {\n throw new Error(\n `Invalid store scheme '${scheme}': must match [a-z][a-z0-9+.-]{0,31}`,\n );\n }\n if (!options?.overwrite && _storeRegistry.has(scheme)) {\n throw new Error(\n `Store scheme '${scheme}' is already registered. Pass { overwrite: true } to replace.`,\n );\n }\n _storeRegistry.set(scheme, factory);\n}\n\nfunction parseStoreUri(uri: string, embeddingDim?: number): BaseStore | AsyncBaseStore {\n if (uri.startsWith(\"sqlite:\")) {\n return new SQLiteStore(parseSqlitePath(uri));\n }\n if (uri.startsWith(\"postgres://\") || uri.startsWith(\"postgresql://\")) {\n throw new Error(\n \"PostgresStore cannot be resolved from URI synchronously. \" +\n \"Import PostgresStore directly and pass it as the store option.\",\n );\n }\n // Check registry for other schemes (e.g. neo4j from mnemonic-platform).\n // Match scheme followed by :// or + (compound schemes like neo4j+s://).\n for (const [scheme, factory] of _storeRegistry) {\n if (uri.startsWith(`${scheme}://`) || uri.startsWith(`${scheme}+`)) {\n const result = factory(uri, embeddingDim);\n if (result instanceof Promise) {\n throw new Error(\n `Store factory for '${scheme}' returned a Promise. ` +\n \"Async store factories must be resolved before passing to Mnemonic.\",\n );\n }\n return result;\n }\n }\n throw new Error(`Unsupported store URI: '${sanitizeUri(uri)}'`);\n}\n\nexport interface AddOptions {\n source?: string;\n actor?: string;\n tier?: string;\n sessionId?: string;\n metadata?: Record<string, unknown>;\n shared?: boolean;\n}\n\nexport interface RecallOptions {\n maxTokens?: number;\n minRelevance?: number;\n header?: string;\n}\n\nexport interface ForgetOptions {\n olderThan?: string;\n tier?: string;\n belowImportance?: number;\n}\n\nexport interface StatsResult {\n totalMemories: number;\n totalTokens: number;\n byTier: Record<string, number>;\n agentId: string;\n}\n\nexport class Mnemonic {\n private _config: MnemonicConfig;\n private _store: AsyncBaseStore;\n private _embedder: BaseEmbedder | null;\n private _autoClassify: boolean;\n private _agentId: string | null;\n private _resolvedAgentId: string | null = null;\n private _initPromise: Promise<void> | null = null;\n\n constructor(options?: {\n store?: string | BaseStore | AsyncBaseStore;\n embedder?: BaseEmbedder | null;\n autoClassify?: boolean;\n config?: MnemonicConfig;\n agentId?: string;\n }) {\n this._config = options?.config ?? new MnemonicConfig();\n this._embedder = options?.embedder ?? null;\n this._autoClassify = options?.autoClassify ?? true;\n this._agentId = options?.agentId ?? null;\n\n const storeOpt = options?.store ?? \"sqlite:///mnemonic.db\";\n if (typeof storeOpt === \"string\") {\n const raw = parseStoreUri(storeOpt, this._embedder?.dimension);\n this._store = _wrapIfSync(raw);\n } else {\n this._store = _wrapIfSync(storeOpt);\n }\n }\n\n get config(): MnemonicConfig {\n return this._config;\n }\n\n /** The underlying async store. */\n get store(): AsyncBaseStore {\n return this._store;\n }\n\n /** The embedder (if configured). */\n get embedder(): BaseEmbedder | null {\n return this._embedder;\n }\n\n /** The resolved agent ID (available after init()). */\n get agentId(): string {\n if (!this._resolvedAgentId) {\n throw new Error(\"Client not initialized. Call init() first.\");\n }\n return this._resolvedAgentId;\n }\n\n /**\n * Initialize the store and resolve agent identity. Must be called before use.\n * Pass `{ skipStoreInit: true }` when reusing an already-initialized store\n * (e.g. creating per-agent clients that share a single backend).\n */\n async init(options?: { skipStoreInit?: boolean }): Promise<void> {\n if (this._resolvedAgentId) return;\n if (this._initPromise) {\n await this._initPromise;\n return;\n }\n this._initPromise = (async () => {\n if (!options?.skipStoreInit) {\n await this._store.initialize();\n }\n await this._resolveAgentId();\n })();\n try {\n await this._initPromise;\n } finally {\n this._initPromise = null;\n }\n }\n\n private async _resolveAgentId(): Promise<void> {\n if (this._agentId) {\n this._resolvedAgentId = this._agentId;\n return;\n }\n const persisted = await this._store.getMeta(\"agent_id\");\n if (persisted) {\n this._resolvedAgentId = persisted;\n return;\n }\n const generated = randomUUID().replace(/-/g, \"\");\n await this._store.setMeta(\"agent_id\", generated);\n this._resolvedAgentId = generated;\n }\n\n private _ensureInitialized(): void {\n if (!this._resolvedAgentId) {\n throw new Error(\"Client not initialized. Call init() first.\");\n }\n }\n\n /** Return only memories owned by this agent (excludes shared from others). */\n private async _ownMemories(): Promise<Memory[]> {\n return this._store.listAll({\n agentId: this._resolvedAgentId!,\n includeShared: false,\n });\n }\n\n private static _contentHash(content: string): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n }\n\n /**\n * Store a memory with automatic classification and linking.\n * If identical content already exists for this agent, returns the existing memory.\n */\n async add(content: string, options?: AddOptions): Promise<Memory> {\n this._ensureInitialized();\n\n const contentHash = Mnemonic._contentHash(content);\n const knownMemories = await this._store.listAll({ agentId: this._resolvedAgentId! });\n for (const mem of knownMemories) {\n if (mem.agentId === this._resolvedAgentId && Mnemonic._contentHash(mem.content) === contentHash) {\n return mem;\n }\n }\n\n const source = options?.source ?? \"unknown\";\n const actor = options?.actor ?? \"system\";\n\n let resolvedTier: string;\n if (options?.tier != null) {\n resolvedTier = options.tier;\n } else if (this._autoClassify) {\n resolvedTier = classify(content, {\n source,\n actor,\n config: this._config,\n });\n } else {\n resolvedTier = this._config.defaultTier;\n }\n\n const memory = new Memory({\n content,\n tier: resolvedTier,\n source,\n actor,\n sessionId: options?.sessionId ?? null,\n metadata: options?.metadata ?? {},\n agentId: this._resolvedAgentId!,\n shared: options?.shared ?? false,\n charsPerToken: this._config.charsPerToken,\n });\n\n // Compute embedding\n if (this._embedder) {\n memory.embedding = await this._embedder.embed(content);\n }\n\n // Salience detection\n const salience = detectSalience(content, this._config.salience);\n if (salience.boost > 0) {\n memory.metadata[\"salience_signals\"] = salience.signals;\n memory.metadata[\"boost\"] =\n ((memory.metadata[\"boost\"] as number) ?? 0) + salience.boost;\n }\n\n // Score\n memory.importance = score(memory, this._config);\n\n // Link to existing memories (loads all agent memories — O(N) scaling\n // limitation matching the Python port; acceptable for typical memory counts)\n const existing = await this._store.listAll({\n agentId: this._resolvedAgentId!,\n });\n const edges = findLinks(memory, existing, { config: this._config });\n\n // Persist the new memory first so that stores with referential checks\n // (e.g. Neo4j MATCH) can resolve both endpoints when saving edges.\n await this._store.save(memory);\n\n for (const edge of edges) {\n memory.linkedIds.push(edge.targetId);\n await this._store.saveEdge(edge);\n const linked = await this._store.get(edge.targetId);\n if (linked) {\n // Only mutate memories owned by the same agent\n if (linked.agentId === this._resolvedAgentId) {\n if (!linked.linkedIds.includes(memory.id)) {\n linked.linkedIds.push(memory.id);\n }\n if (edge.relation === \"supersedes\" && linked.supersededBy == null) {\n linked.supersededBy = memory.id;\n } else if (edge.relation === \"contradicts\" && linked.contradictedBy == null) {\n linked.contradictedBy = memory.id;\n }\n await this._store.save(linked);\n }\n }\n }\n\n // Final save to persist linkedIds accumulated during edge iteration\n await this._store.save(memory);\n return memory;\n }\n\n private async _assemble(\n query: string,\n options?: { maxTokens?: number; minRelevance?: number; excludeSuperseded?: boolean },\n ): Promise<Memory[]> {\n let queryEmbedding: number[] | null = null;\n const limit = this._config.embeddingSearchLimit;\n\n let candidates: Memory[];\n if (this._embedder) {\n queryEmbedding = await this._embedder.embed(query);\n candidates = await this._store.searchByEmbedding(\n queryEmbedding,\n limit,\n { agentId: this._resolvedAgentId! },\n );\n } else {\n candidates = await this._store.listAll({\n agentId: this._resolvedAgentId!,\n });\n }\n\n if (options?.excludeSuperseded) {\n candidates = candidates.filter((m) => m.supersededBy == null);\n }\n\n const selected = assemble(query, candidates, {\n queryEmbedding,\n maxTokens: options?.maxTokens,\n minRelevance: options?.minRelevance,\n config: this._config,\n });\n\n await Promise.all(selected.map((mem) => this._store.save(mem)));\n\n return selected;\n }\n\n /** Retrieve optimised context for a given query within a token budget. */\n async recall(query: string, options?: RecallOptions): Promise<string> {\n this._ensureInitialized();\n const selected = await this._assemble(query, {\n ...options,\n excludeSuperseded: true,\n });\n const conflicts = detectConflicts(selected, this._config);\n return formatContext(selected, options?.header, conflicts);\n }\n\n /** Like recall but returns the raw Memory objects. */\n async recallMemories(\n query: string,\n options?: { maxTokens?: number; minRelevance?: number },\n ): Promise<Memory[]> {\n this._ensureInitialized();\n return this._assemble(query, options);\n }\n\n /** Delete memories matching the given criteria. Returns count deleted. */\n async forget(options?: ForgetOptions): Promise<number> {\n this._ensureInitialized();\n if (\n !options?.olderThan &&\n !options?.tier &&\n options?.belowImportance == null\n ) {\n throw new Error(\n \"forget() requires at least one filter (olderThan, tier, or belowImportance)\",\n );\n }\n\n const tier = options?.tier;\n\n if (options?.belowImportance == null) {\n const olderThan = options?.olderThan?.trim();\n if (olderThan === \"\") {\n throw new Error(\"olderThan must be a valid duration string (e.g. '30d'), not empty\");\n }\n const ageMs = olderThan ? parseDuration(olderThan) : 0;\n return this._store.deleteOlderThan(ageMs, tier, {\n agentId: this._resolvedAgentId!,\n });\n }\n\n // Decay-aware path: push tier filter to store to avoid loading all memories.\n let candidates = await this._store.listAll({\n agentId: this._resolvedAgentId!,\n includeShared: false,\n tier: tier ?? undefined,\n });\n if (options?.olderThan != null) {\n const ageMs = parseDuration(options.olderThan);\n const cutoff = Date.now() - ageMs;\n candidates = candidates.filter((m) => m.createdAt.getTime() < cutoff);\n }\n\n let deleted = 0;\n for (const mem of candidates) {\n const currentImportance = score(mem, this._config);\n if (currentImportance < options.belowImportance) {\n await this._store.delete(mem.id);\n deleted++;\n }\n }\n return deleted;\n }\n\n /**\n * Merge similar episodic memories into higher-tier summaries.\n *\n * Originals are kept alive but deprioritised via a scoring penalty\n * and `consolidated_into` metadata. A `consolidates` edge links\n * the summary to each original for graph traversal.\n */\n async consolidate(): Promise<number> {\n this._ensureInitialized();\n // Load only episodic memories — avoids loading identity/structural/procedural/transient\n // memories (and their embeddings) that consolidation can't use.\n const ownEpisodic = await this._store.listAll({\n agentId: this._resolvedAgentId!,\n includeShared: false,\n tier: MemoryTier.EPISODIC,\n });\n\n // Exclude already-consolidated originals so consolidate() is idempotent.\n // Also re-include orphaned originals whose summary was deleted.\n const eligible: Memory[] = [];\n for (const m of ownEpisodic) {\n const summaryId = m.metadata[\"consolidated_into\"] as string | undefined;\n if (summaryId == null || (await this._store.get(summaryId)) == null) {\n eligible.push(m);\n }\n }\n\n // Partition by shared flag so private and shared never mix\n const privateMemories = eligible.filter((m) => !m.shared);\n const sharedMemories = eligible.filter((m) => m.shared);\n\n // Get sparse similarity pairs from the store (uses ANN on Postgres/Neo4j,\n // brute-force with cap on SQLite).\n const cfg = this._config.consolidation;\n const eligibleIds = new Set(eligible.map((m) => m.id));\n const allPairs = await this._store.findSimilarPairs({\n threshold: cfg.similarityThreshold,\n agentId: this._resolvedAgentId!,\n tier: MemoryTier.EPISODIC,\n maxCandidates: cfg.maxCandidates,\n maxNeighborsPerCandidate: cfg.maxNeighborsPerCandidate,\n });\n // Filter to eligible memories — already-consolidated originals may appear\n // in the store's candidate set but should not consume pair budget.\n const eligiblePairs = allPairs.filter(\n (p) => eligibleIds.has(p.idA) && eligibleIds.has(p.idB),\n );\n\n // Partition pairs to match the private/shared split.\n const privateIds = new Set(privateMemories.map((m) => m.id));\n const sharedIds = new Set(sharedMemories.map((m) => m.id));\n const privatePairs = eligiblePairs.filter(\n (p) => privateIds.has(p.idA) && privateIds.has(p.idB),\n );\n const sharedPairs = eligiblePairs.filter(\n (p) => sharedIds.has(p.idA) && sharedIds.has(p.idB),\n );\n\n let totalClusters = 0;\n\n for (const [memories, pairs, isShared] of [\n [privateMemories, privatePairs, false],\n [sharedMemories, sharedPairs, true],\n ] as const) {\n const clusters = findConsolidationCandidates(memories, this._config, pairs);\n\n // Phase 1: Summarize + embed clusters with bounded concurrency.\n // Each cluster is independent (disjoint by union-find), so parallel\n // processing is safe. Cap concurrency to avoid overwhelming the LLM\n // API with hundreds of simultaneous requests at scale.\n const CONCURRENCY = 8;\n const prepared: Array<{\n cluster: Memory[];\n summary: Memory;\n }> = [];\n\n const processBatch = async (batch: Memory[][]) => {\n const results = await Promise.all(\n batch.map(async (cluster) => {\n const summary = await mergeCluster(cluster, this._config);\n summary.agentId = this._resolvedAgentId!;\n summary.shared = isShared;\n for (const mem of cluster) {\n if (!summary.linkedIds.includes(mem.id)) {\n summary.linkedIds.push(mem.id);\n }\n }\n if (this._embedder) {\n summary.embedding = await this._embedder.embed(summary.content);\n }\n summary.importance = score(summary, this._config);\n return { cluster, summary };\n }),\n );\n prepared.push(...results);\n };\n\n for (let i = 0; i < clusters.length; i += CONCURRENCY) {\n await processBatch(clusters.slice(i, i + CONCURRENCY));\n }\n\n // Phase 2: Persist sequentially (store backends may serialise writes).\n for (const { cluster, summary } of prepared) {\n await this._store.save(summary);\n for (const mem of cluster) {\n const edge = createEdge(summary.id, mem.id, \"consolidates\");\n await this._store.saveEdge(edge);\n mem.metadata[\"consolidated_into\"] = summary.id;\n mem.linkedIds.push(summary.id);\n mem.importance = score(mem, this._config);\n await this._store.save(mem);\n }\n }\n totalClusters += clusters.length;\n }\n\n return totalClusters;\n }\n\n /** Run the tier promotion/demotion pipeline on own memories. */\n async promote(): Promise<number> {\n this._ensureInitialized();\n const ownMemories = await this._ownMemories();\n let changes = await this._applyTierResults(\n checkPromotions(ownMemories, this._config),\n );\n\n const refreshed = await this._ownMemories();\n changes += await this._applyTierResults(\n checkDemotions(refreshed, this._config),\n );\n\n return changes;\n }\n\n /** Re-run the linker across all memories to retroactively set edges. */\n async relink(): Promise<number> {\n this._ensureInitialized();\n const ownMemories = await this._ownMemories();\n const visible = await this._store.listAll({ agentId: this._resolvedAgentId! });\n const ownById = new Map(ownMemories.map((m) => [m.id, m]));\n const existingRelations = new Map<string, string>();\n\n for (const mem of ownMemories) {\n const edges = await this._store.getEdges(mem.id);\n for (const e of edges) existingRelations.set(`${e.sourceId}:${e.targetId}`, e.relation);\n }\n\n let newEdges = 0;\n for (const mem of ownMemories) {\n const edges = findLinks(mem, visible, { config: this._config });\n for (const edge of edges) {\n const key = `${edge.sourceId}:${edge.targetId}`;\n const existingRel = existingRelations.get(key);\n\n if (existingRel == null) {\n await this._store.saveEdge(edge);\n existingRelations.set(key, edge.relation);\n newEdges++;\n } else if (existingRel !== edge.relation) {\n await this._store.saveEdge(edge);\n existingRelations.set(key, edge.relation);\n }\n\n // Backfill linked_ids and metadata.\n if (edge.targetId !== mem.id && !mem.linkedIds.includes(edge.targetId)) {\n mem.linkedIds.push(edge.targetId);\n }\n const linked = ownById.get(edge.targetId);\n if (linked) {\n if (!linked.linkedIds.includes(mem.id)) linked.linkedIds.push(mem.id);\n if (edge.relation === \"supersedes\" && linked.supersededBy == null) {\n linked.supersededBy = mem.id;\n } else if (edge.relation === \"contradicts\" && linked.contradictedBy == null) {\n linked.contradictedBy = mem.id;\n }\n }\n }\n }\n // Save all memories in one pass — avoids ordering issues where\n // a target memory is modified after its own outer-loop save.\n await Promise.all(ownMemories.map((m) => this._store.save(m)));\n return newEdges;\n }\n\n /** Return aggregate statistics about own memories. */\n async stats(): Promise<StatsResult> {\n this._ensureInitialized();\n const memories = await this._ownMemories();\n const byTier: Record<string, number> = {};\n let totalTokens = 0;\n for (const m of memories) {\n byTier[m.tierName] = (byTier[m.tierName] ?? 0) + 1;\n totalTokens += m.tokenEstimate;\n }\n return {\n totalMemories: memories.length,\n totalTokens,\n byTier,\n agentId: this._resolvedAgentId!,\n };\n }\n\n /** Make a memory visible to all agents. */\n async share(memoryId: string): Promise<Memory> {\n this._ensureInitialized();\n const memory = await this._store.get(memoryId);\n if (!memory) {\n throw new Error(`Memory not found: ${memoryId}`);\n }\n if (memory.agentId !== this._resolvedAgentId) {\n throw new Error(\"Cannot share another agent's memory\");\n }\n memory.shared = true;\n await this._store.save(memory);\n return memory;\n }\n\n /** Make a memory private (only visible to owner). */\n async unshare(memoryId: string): Promise<Memory> {\n this._ensureInitialized();\n const memory = await this._store.get(memoryId);\n if (!memory) {\n throw new Error(`Memory not found: ${memoryId}`);\n }\n if (memory.agentId !== this._resolvedAgentId) {\n throw new Error(\"Cannot unshare another agent's memory\");\n }\n memory.shared = false;\n await this._store.save(memory);\n return memory;\n }\n\n private async _applyTierResults(\n results: Array<{ memoryId: string; newTier: string }>,\n ): Promise<number> {\n let applied = 0;\n for (const result of results) {\n const mem = await this._store.get(result.memoryId);\n if (!mem) continue;\n applyTierChange(mem, result.newTier);\n mem.importance = score(mem, this._config);\n await this._store.save(mem);\n applied++;\n }\n return applied;\n }\n}\n\n/**\n * Wrap a sync BaseStore into AsyncBaseStore. Async stores pass through.\n * Known sync stores are detected by instanceof. Custom sync stores should\n * call syncToAsync() themselves before passing to the Mnemonic constructor.\n */\nfunction _wrapIfSync(store: BaseStore | AsyncBaseStore): AsyncBaseStore {\n if (store instanceof SQLiteStore) {\n return syncToAsync(store);\n }\n // Assume anything else is already async (PostgresStore, Neo4jStore, etc.)\n return store as AsyncBaseStore;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,375 @@
1
+ import {
2
+ buildEmbedder
3
+ } from "./chunk-CZDK53NR.js";
4
+ import {
5
+ Mnemonic,
6
+ SQLiteStore,
7
+ _registeredStores
8
+ } from "./chunk-NA7L5FQN.js";
9
+ import {
10
+ parseSqlitePath
11
+ } from "./chunk-5Z46NSNR.js";
12
+
13
+ // src/mcp/server.ts
14
+ var MAX_AGENT_CACHE = 256;
15
+ var AGENT_ID_RE = /^[a-zA-Z0-9_-]{1,128}$/;
16
+ function validateAgentId(agentId) {
17
+ const trimmed = agentId.trim();
18
+ if (!AGENT_ID_RE.test(trimmed)) {
19
+ throw new Error(
20
+ "Invalid agent_id: must be 1-128 alphanumeric/underscore/hyphen characters"
21
+ );
22
+ }
23
+ return trimmed;
24
+ }
25
+ function serializeMemory(memory, callerAgentId) {
26
+ return {
27
+ id: memory.id,
28
+ content: memory.content,
29
+ tier: memory.tierName,
30
+ source: memory.source,
31
+ actor: memory.actor,
32
+ session_id: memory.sessionId,
33
+ created_at: memory.createdAt.toISOString(),
34
+ last_accessed_at: memory.lastAccessedAt.toISOString(),
35
+ access_count: memory.accessCount,
36
+ importance: Math.round(memory.importance * 1e4) / 1e4,
37
+ superseded_by: memory.supersededBy,
38
+ contradicted_by: memory.contradictedBy,
39
+ has_embedding: memory.embedding != null,
40
+ metadata: memory.metadata,
41
+ linked_ids: memory.linkedIds,
42
+ token_estimate: memory.tokenEstimate,
43
+ owned_by_caller: callerAgentId != null ? memory.agentId === callerAgentId : false,
44
+ shared: memory.shared
45
+ };
46
+ }
47
+ async function buildFromUri(uri) {
48
+ const embedder = await buildEmbedder();
49
+ const dim = embedder?.dimension ?? 1536;
50
+ if (uri.startsWith("sqlite:")) {
51
+ return { store: new SQLiteStore(parseSqlitePath(uri)), embedder };
52
+ }
53
+ if (uri.startsWith("postgres://") || uri.startsWith("postgresql://")) {
54
+ const { PostgresStore } = await import("./postgres-GQ6DZDBW.js");
55
+ return { store: new PostgresStore({ dsn: uri, embeddingDim: dim }), embedder };
56
+ }
57
+ for (const [scheme, factory] of _registeredStores()) {
58
+ if (uri.startsWith(`${scheme}://`) || uri.startsWith(`${scheme}+`)) {
59
+ const result = factory(uri, dim);
60
+ const store = result instanceof Promise ? await result : result;
61
+ return { store, embedder };
62
+ }
63
+ }
64
+ throw new Error(
65
+ `Unsupported store URI: '${uri}'. Use sqlite:///path, postgres[ql]://..., or register a custom store.`
66
+ );
67
+ }
68
+ async function createServer(options) {
69
+ let mcpSdk;
70
+ try {
71
+ const mcpPath = "@modelcontextprotocol/sdk/server/mcp.js";
72
+ mcpSdk = await import(mcpPath);
73
+ } catch {
74
+ throw new Error(
75
+ "MCP server requires '@modelcontextprotocol/sdk'. Install it with: npm install @modelcontextprotocol/sdk"
76
+ );
77
+ }
78
+ const { McpServer } = mcpSdk;
79
+ let z;
80
+ try {
81
+ const zodPath = "zod";
82
+ const zod = await import(zodPath);
83
+ z = zod.z ?? zod.default?.z;
84
+ } catch {
85
+ throw new Error(
86
+ "MCP server requires 'zod'. Install it with: npm install zod"
87
+ );
88
+ }
89
+ let baseClient;
90
+ if (options?.mnemonic) {
91
+ baseClient = options.mnemonic;
92
+ try {
93
+ baseClient.agentId;
94
+ } catch {
95
+ await baseClient.init();
96
+ }
97
+ } else {
98
+ const storeUri = process.env["MNEMONIC_STORE_URI"] ?? "sqlite:///mnemonic.db";
99
+ const agentId = process.env["MNEMONIC_AGENT_ID"] || void 0;
100
+ const { store, embedder } = await buildFromUri(storeUri);
101
+ baseClient = new Mnemonic({ store, embedder, agentId });
102
+ await baseClient.init();
103
+ }
104
+ const agentCache = /* @__PURE__ */ new Map();
105
+ async function getAgent(agentId) {
106
+ if (!agentId) return baseClient;
107
+ agentId = validateAgentId(agentId);
108
+ const cached = agentCache.get(agentId);
109
+ if (cached) {
110
+ agentCache.delete(agentId);
111
+ agentCache.set(agentId, cached);
112
+ return cached;
113
+ }
114
+ if (agentCache.size >= MAX_AGENT_CACHE) {
115
+ const lru = agentCache.keys().next().value;
116
+ agentCache.delete(lru);
117
+ }
118
+ const agent = new Mnemonic({
119
+ store: baseClient.store,
120
+ embedder: baseClient.embedder,
121
+ config: baseClient.config,
122
+ agentId
123
+ });
124
+ await agent.init({ skipStoreInit: true });
125
+ agentCache.set(agentId, agent);
126
+ return agent;
127
+ }
128
+ function jsonResponse(data) {
129
+ return {
130
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
131
+ };
132
+ }
133
+ function errorResponse(err) {
134
+ const message = err instanceof Error ? err.message : String(err);
135
+ let hint = "";
136
+ if (message.includes("not found")) hint = " Use memory_search to find valid IDs.";
137
+ else if (message.includes("not the owner") || message.includes("permission")) hint = " Only the owning agent can modify this memory.";
138
+ else if (message.includes("at least one filter")) hint = " Provide older_than, tier, or below_importance.";
139
+ return {
140
+ content: [
141
+ {
142
+ type: "text",
143
+ text: JSON.stringify({ error: message + hint }, null, 2)
144
+ }
145
+ ],
146
+ isError: true
147
+ };
148
+ }
149
+ const server = new McpServer({
150
+ name: "mnemonic",
151
+ version: "0.1.0"
152
+ });
153
+ server.tool(
154
+ "memory_store",
155
+ {
156
+ description: "Save information to long-term memory. Call proactively when the user shares preferences, identity facts, decisions, corrections, or notable events \u2014 also when they correct prior knowledge or express a strong preference. Auto-classifies into tiers, scores importance, links to related memories, and detects supersession.",
157
+ annotations: { readOnlyHint: false, idempotentHint: false }
158
+ },
159
+ {
160
+ content: z.string().describe("Clear standalone statement to remember, e.g. 'User prefers Kubernetes over ECS' or 'Project uses Next.js 14 with App Router'"),
161
+ source: z.string().default("conversation").describe("Where this came from. Use lowercase_snake values. Common: 'conversation', 'observation', 'document', 'tool_output', 'system'. Custom sources welcome: 'slack', 'email', 'jira', 'meeting_notes', etc."),
162
+ actor: z.string().default("user").describe("Who produced this. Common: 'user', 'assistant', 'system'. Can also be a specific name or agent ID."),
163
+ tier: z.enum(["identity", "procedural", "structural", "episodic", "transient"]).optional().describe("Override auto-classification. Usually omit \u2014 the classifier handles it."),
164
+ session_id: z.string().optional().describe("Group memories by conversation or task"),
165
+ metadata: z.record(z.unknown()).optional().describe("Key-value pairs, e.g. {project: 'api', priority: 'high'}"),
166
+ agent_id: z.string().optional().describe("Target agent's memory space. Omit for default."),
167
+ shared: z.boolean().optional().describe("Make visible to all agents. Default: false.")
168
+ },
169
+ async (params) => {
170
+ try {
171
+ const agent = await getAgent(params.agent_id);
172
+ const memory = await agent.add(params.content, {
173
+ source: params.source,
174
+ actor: params.actor,
175
+ tier: params.tier,
176
+ sessionId: params.session_id,
177
+ metadata: params.metadata,
178
+ shared: params.shared
179
+ });
180
+ return jsonResponse(serializeMemory(memory, agent.agentId));
181
+ } catch (err) {
182
+ return errorResponse(err);
183
+ }
184
+ }
185
+ );
186
+ server.tool(
187
+ "memory_recall",
188
+ {
189
+ description: "Retrieve relevant memories as formatted text, ranked by relevance and importance within a token budget. Call at the start of every conversation to load context. Also call when the topic shifts or when you need to verify what you already know. Returns a ready-to-use text block. Prefer over memory_search unless you need structured data or memory IDs.",
190
+ annotations: { readOnlyHint: true, idempotentHint: true }
191
+ },
192
+ {
193
+ query: z.string().describe("What you need to know, e.g. 'deployment preferences' or 'user's tech stack'"),
194
+ max_tokens: z.number().int().min(100).max(16e3).optional().describe("Token budget for returned context. Default: 2000."),
195
+ min_relevance: z.number().min(0).max(1).optional().describe("Minimum relevance score (0.0-1.0) for a memory to be included. Filters out low-relevance noise."),
196
+ header: z.string().optional().describe("Header prepended to context, e.g. '## Relevant Memory'"),
197
+ agent_id: z.string().optional().describe("Target agent's memory space. Omit for default.")
198
+ },
199
+ async (params) => {
200
+ try {
201
+ const agent = await getAgent(params.agent_id);
202
+ const context = await agent.recall(params.query, {
203
+ maxTokens: params.max_tokens,
204
+ minRelevance: params.min_relevance,
205
+ header: params.header
206
+ });
207
+ return { content: [{ type: "text", text: context }] };
208
+ } catch (err) {
209
+ return errorResponse(err);
210
+ }
211
+ }
212
+ );
213
+ server.tool(
214
+ "memory_search",
215
+ {
216
+ description: "Search memories and return structured JSON with full metadata (id, tier, importance, timestamps, linked_ids). Use instead of memory_recall when you need memory IDs for share/unshare/forget, or need to inspect importance scores and graph links.",
217
+ annotations: { readOnlyHint: true, idempotentHint: true }
218
+ },
219
+ {
220
+ query: z.string().describe("What to search for, e.g. 'infrastructure decisions' or 'recent debugging sessions'"),
221
+ max_tokens: z.number().int().min(100).max(16e3).optional().describe("Token budget for candidate selection. Default: 2000."),
222
+ min_relevance: z.number().min(0).max(1).optional().describe("Minimum relevance score (0.0-1.0) for a memory to be included. Filters out low-relevance noise."),
223
+ agent_id: z.string().optional().describe("Target agent's memory space. Omit for default.")
224
+ },
225
+ async (params) => {
226
+ try {
227
+ const agent = await getAgent(params.agent_id);
228
+ const memories = await agent.recallMemories(params.query, {
229
+ maxTokens: params.max_tokens,
230
+ minRelevance: params.min_relevance
231
+ });
232
+ return jsonResponse(memories.map((m) => serializeMemory(m, agent.agentId)));
233
+ } catch (err) {
234
+ return errorResponse(err);
235
+ }
236
+ }
237
+ );
238
+ server.tool(
239
+ "memory_forget",
240
+ {
241
+ description: "Delete memories matching filters. Memories naturally fade via decay \u2014 only explicitly delete when content is wrong, sensitive, or the user requests removal. At least one filter is required.",
242
+ annotations: { destructiveHint: true, idempotentHint: false }
243
+ },
244
+ {
245
+ older_than: z.string().optional().describe("Delete older than duration: '30d', '24h', '2w', '90m', '120s'"),
246
+ tier: z.enum(["identity", "procedural", "structural", "episodic", "transient"]).optional().describe("Only delete memories in this tier"),
247
+ below_importance: z.number().min(0).max(1).optional().describe("Delete below this importance score (0.0\u20131.0)"),
248
+ agent_id: z.string().optional().describe("Target agent's memory space. Omit for default.")
249
+ },
250
+ async (params) => {
251
+ try {
252
+ const agent = await getAgent(params.agent_id);
253
+ const deleted = await agent.forget({
254
+ olderThan: params.older_than,
255
+ tier: params.tier,
256
+ belowImportance: params.below_importance
257
+ });
258
+ return jsonResponse({ deleted });
259
+ } catch (err) {
260
+ return errorResponse(err);
261
+ }
262
+ }
263
+ );
264
+ server.tool(
265
+ "memory_consolidate",
266
+ {
267
+ description: "Merge similar episodic memories into structural summaries. Originals are kept but deprioritised \u2014 they fade naturally via decay while the summary takes over in recall. Run after storing 10+ memories in a session, or when memory_stats shows many episodic memories.",
268
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false }
269
+ },
270
+ { agent_id: z.string().optional().describe("Target agent. Omit for default.") },
271
+ async (params) => {
272
+ try {
273
+ const agent = await getAgent(params.agent_id);
274
+ return jsonResponse({ consolidated_groups: await agent.consolidate() });
275
+ } catch (err) {
276
+ return errorResponse(err);
277
+ }
278
+ }
279
+ );
280
+ server.tool(
281
+ "memory_promote",
282
+ {
283
+ description: "Promote frequently accessed memories to higher tiers and demote inactive ones. Tiers affect recall ranking and decay rate. Run at the end of sessions to update tier rankings based on access patterns.",
284
+ annotations: { readOnlyHint: false, idempotentHint: false }
285
+ },
286
+ { agent_id: z.string().optional().describe("Target agent. Omit for default.") },
287
+ async (params) => {
288
+ try {
289
+ const agent = await getAgent(params.agent_id);
290
+ return jsonResponse({ tier_changes: await agent.promote() });
291
+ } catch (err) {
292
+ return errorResponse(err);
293
+ }
294
+ }
295
+ );
296
+ server.tool(
297
+ "memory_relink",
298
+ {
299
+ description: "Re-run the linker across all memories to retroactively detect supersession and contradiction edges. Use after upgrading or when existing memories lack relationship metadata.",
300
+ annotations: { readOnlyHint: false, idempotentHint: true }
301
+ },
302
+ { agent_id: z.string().optional().describe("Target agent. Omit for default.") },
303
+ async (params) => {
304
+ try {
305
+ const agent = await getAgent(params.agent_id);
306
+ return jsonResponse({ new_edges: await agent.relink() });
307
+ } catch (err) {
308
+ return errorResponse(err);
309
+ }
310
+ }
311
+ );
312
+ server.tool(
313
+ "memory_stats",
314
+ {
315
+ description: "Get memory health: total count, tier breakdown, token usage. Call when the user asks 'what do you remember?' or to decide if consolidation or pruning is needed.",
316
+ annotations: { readOnlyHint: true, idempotentHint: true }
317
+ },
318
+ { agent_id: z.string().optional().describe("Target agent. Omit for default.") },
319
+ async (params) => {
320
+ try {
321
+ const agent = await getAgent(params.agent_id);
322
+ return jsonResponse(await agent.stats());
323
+ } catch (err) {
324
+ return errorResponse(err);
325
+ }
326
+ }
327
+ );
328
+ server.tool(
329
+ "memory_share",
330
+ {
331
+ description: "Make a memory visible to all agents. Only the owning agent can share. Use memory_search first to get the memory ID.",
332
+ annotations: { readOnlyHint: false, idempotentHint: true }
333
+ },
334
+ {
335
+ memory_id: z.string().describe("Memory ID from memory_search results"),
336
+ agent_id: z.string().optional().describe("Owning agent. Omit for default.")
337
+ },
338
+ async (params) => {
339
+ try {
340
+ const agent = await getAgent(params.agent_id);
341
+ const memory = await agent.share(params.memory_id);
342
+ return jsonResponse(serializeMemory(memory, agent.agentId));
343
+ } catch (err) {
344
+ return errorResponse(err);
345
+ }
346
+ }
347
+ );
348
+ server.tool(
349
+ "memory_unshare",
350
+ {
351
+ description: "Make a shared memory private again. Only the owning agent can unshare. Use memory_search first to get the memory ID.",
352
+ annotations: { readOnlyHint: false, idempotentHint: true }
353
+ },
354
+ {
355
+ memory_id: z.string().describe("Memory ID from memory_search results"),
356
+ agent_id: z.string().optional().describe("Owning agent. Omit for default.")
357
+ },
358
+ async (params) => {
359
+ try {
360
+ const agent = await getAgent(params.agent_id);
361
+ const memory = await agent.unshare(params.memory_id);
362
+ return jsonResponse(serializeMemory(memory, agent.agentId));
363
+ } catch (err) {
364
+ return errorResponse(err);
365
+ }
366
+ }
367
+ );
368
+ return { server, baseClient, agentCache };
369
+ }
370
+
371
+ export {
372
+ serializeMemory,
373
+ createServer
374
+ };
375
+ //# sourceMappingURL=chunk-OEEEWS2M.js.map