@mnemoai/core 1.1.2 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +26 -0
- package/README.md +321 -0
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +0 -1
- package/dist/index.d.ts +0 -115
- package/dist/index.js +1 -6
- package/dist/src/access-tracker.d.ts +0 -1
- package/dist/src/access-tracker.js +0 -1
- package/dist/src/adapters/chroma.d.ts +0 -1
- package/dist/src/adapters/chroma.js +0 -1
- package/dist/src/adapters/lancedb.d.ts +0 -1
- package/dist/src/adapters/lancedb.js +0 -1
- package/dist/src/adapters/pgvector.d.ts +0 -1
- package/dist/src/adapters/pgvector.js +0 -1
- package/dist/src/adapters/qdrant.d.ts +0 -1
- package/dist/src/adapters/qdrant.js +0 -1
- package/dist/src/adaptive-retrieval.d.ts +0 -1
- package/dist/src/adaptive-retrieval.js +0 -1
- package/dist/src/audit-log.d.ts +0 -1
- package/dist/src/audit-log.js +0 -1
- package/dist/src/chunker.d.ts +0 -1
- package/dist/src/chunker.js +0 -1
- package/dist/src/config.d.ts +0 -1
- package/dist/src/config.js +0 -1
- package/dist/src/decay-engine.d.ts +0 -1
- package/dist/src/decay-engine.js +0 -1
- package/dist/src/embedder.d.ts +0 -1
- package/dist/src/embedder.js +0 -1
- package/dist/src/extraction-prompts.d.ts +0 -1
- package/dist/src/extraction-prompts.js +0 -1
- package/dist/src/license.d.ts +0 -1
- package/dist/src/license.js +2 -6
- package/dist/src/llm-client.d.ts +0 -1
- package/dist/src/llm-client.js +0 -1
- package/dist/src/logger.d.ts +0 -1
- package/dist/src/logger.js +0 -1
- package/dist/src/mcp-server.d.ts +0 -1
- package/dist/src/mcp-server.js +0 -1
- package/dist/src/memory-categories.d.ts +0 -1
- package/dist/src/memory-categories.js +0 -1
- package/dist/src/memory-upgrader.d.ts +0 -1
- package/dist/src/memory-upgrader.js +0 -1
- package/dist/src/migrate.d.ts +0 -1
- package/dist/src/migrate.js +0 -1
- package/dist/src/mnemo.d.ts +7 -1
- package/dist/src/mnemo.js +19 -7
- package/dist/src/noise-filter.d.ts +0 -1
- package/dist/src/noise-filter.js +0 -1
- package/dist/src/noise-prototypes.d.ts +0 -1
- package/dist/src/noise-prototypes.js +0 -1
- package/dist/src/observability.d.ts +0 -1
- package/dist/src/observability.js +0 -1
- package/dist/src/query-tracker.d.ts +0 -1
- package/dist/src/query-tracker.js +0 -1
- package/dist/src/reflection-event-store.d.ts +0 -1
- package/dist/src/reflection-event-store.js +0 -1
- package/dist/src/reflection-item-store.d.ts +0 -1
- package/dist/src/reflection-item-store.js +0 -1
- package/dist/src/reflection-mapped-metadata.d.ts +0 -1
- package/dist/src/reflection-mapped-metadata.js +0 -1
- package/dist/src/reflection-metadata.d.ts +0 -1
- package/dist/src/reflection-metadata.js +0 -1
- package/dist/src/reflection-ranking.d.ts +0 -1
- package/dist/src/reflection-ranking.js +0 -1
- package/dist/src/reflection-retry.d.ts +0 -1
- package/dist/src/reflection-retry.js +0 -1
- package/dist/src/reflection-slices.d.ts +0 -1
- package/dist/src/reflection-slices.js +0 -1
- package/dist/src/reflection-store.d.ts +0 -1
- package/dist/src/reflection-store.js +0 -1
- package/dist/src/resonance-state.d.ts +0 -1
- package/dist/src/resonance-state.js +0 -1
- package/dist/src/retriever.d.ts +0 -1
- package/dist/src/retriever.js +0 -1
- package/dist/src/scopes.d.ts +0 -1
- package/dist/src/scopes.js +0 -1
- package/dist/src/self-improvement-files.d.ts +0 -1
- package/dist/src/self-improvement-files.js +0 -1
- package/dist/src/semantic-gate.d.ts +0 -1
- package/dist/src/semantic-gate.js +0 -1
- package/dist/src/session-recovery.d.ts +0 -1
- package/dist/src/session-recovery.js +0 -1
- package/dist/src/smart-extractor.d.ts +0 -1
- package/dist/src/smart-extractor.js +0 -1
- package/dist/src/smart-metadata.d.ts +0 -1
- package/dist/src/smart-metadata.js +0 -1
- package/dist/src/storage-adapter.d.ts +0 -1
- package/dist/src/storage-adapter.js +0 -1
- package/dist/src/store.d.ts +0 -1
- package/dist/src/store.js +0 -1
- package/dist/src/tier-manager.d.ts +0 -1
- package/dist/src/tier-manager.js +0 -1
- package/dist/src/tools.d.ts +0 -1
- package/dist/src/tools.js +0 -1
- package/dist/src/wal-recovery.d.ts +0 -1
- package/dist/src/wal-recovery.js +0 -1
- package/package.json +2 -2
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -7
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -7
- package/dist/src/access-tracker.d.ts.map +0 -1
- package/dist/src/access-tracker.js.map +0 -7
- package/dist/src/adapters/chroma.d.ts.map +0 -1
- package/dist/src/adapters/chroma.js.map +0 -7
- package/dist/src/adapters/lancedb.d.ts.map +0 -1
- package/dist/src/adapters/lancedb.js.map +0 -7
- package/dist/src/adapters/pgvector.d.ts.map +0 -1
- package/dist/src/adapters/pgvector.js.map +0 -7
- package/dist/src/adapters/qdrant.d.ts.map +0 -1
- package/dist/src/adapters/qdrant.js.map +0 -7
- package/dist/src/adaptive-retrieval.d.ts.map +0 -1
- package/dist/src/adaptive-retrieval.js.map +0 -7
- package/dist/src/audit-log.d.ts.map +0 -1
- package/dist/src/audit-log.js.map +0 -7
- package/dist/src/chunker.d.ts.map +0 -1
- package/dist/src/chunker.js.map +0 -7
- package/dist/src/config.d.ts.map +0 -1
- package/dist/src/config.js.map +0 -7
- package/dist/src/decay-engine.d.ts.map +0 -1
- package/dist/src/decay-engine.js.map +0 -7
- package/dist/src/embedder.d.ts.map +0 -1
- package/dist/src/embedder.js.map +0 -7
- package/dist/src/extraction-prompts.d.ts.map +0 -1
- package/dist/src/extraction-prompts.js.map +0 -7
- package/dist/src/license.d.ts.map +0 -1
- package/dist/src/license.js.map +0 -7
- package/dist/src/llm-client.d.ts.map +0 -1
- package/dist/src/llm-client.js.map +0 -7
- package/dist/src/logger.d.ts.map +0 -1
- package/dist/src/logger.js.map +0 -7
- package/dist/src/mcp-server.d.ts.map +0 -1
- package/dist/src/mcp-server.js.map +0 -7
- package/dist/src/memory-categories.d.ts.map +0 -1
- package/dist/src/memory-categories.js.map +0 -7
- package/dist/src/memory-upgrader.d.ts.map +0 -1
- package/dist/src/memory-upgrader.js.map +0 -7
- package/dist/src/migrate.d.ts.map +0 -1
- package/dist/src/migrate.js.map +0 -7
- package/dist/src/mnemo.d.ts.map +0 -1
- package/dist/src/mnemo.js.map +0 -7
- package/dist/src/noise-filter.d.ts.map +0 -1
- package/dist/src/noise-filter.js.map +0 -7
- package/dist/src/noise-prototypes.d.ts.map +0 -1
- package/dist/src/noise-prototypes.js.map +0 -7
- package/dist/src/observability.d.ts.map +0 -1
- package/dist/src/observability.js.map +0 -7
- package/dist/src/query-tracker.d.ts.map +0 -1
- package/dist/src/query-tracker.js.map +0 -7
- package/dist/src/reflection-event-store.d.ts.map +0 -1
- package/dist/src/reflection-event-store.js.map +0 -7
- package/dist/src/reflection-item-store.d.ts.map +0 -1
- package/dist/src/reflection-item-store.js.map +0 -7
- package/dist/src/reflection-mapped-metadata.d.ts.map +0 -1
- package/dist/src/reflection-mapped-metadata.js.map +0 -7
- package/dist/src/reflection-metadata.d.ts.map +0 -1
- package/dist/src/reflection-metadata.js.map +0 -7
- package/dist/src/reflection-ranking.d.ts.map +0 -1
- package/dist/src/reflection-ranking.js.map +0 -7
- package/dist/src/reflection-retry.d.ts.map +0 -1
- package/dist/src/reflection-retry.js.map +0 -7
- package/dist/src/reflection-slices.d.ts.map +0 -1
- package/dist/src/reflection-slices.js.map +0 -7
- package/dist/src/reflection-store.d.ts.map +0 -1
- package/dist/src/reflection-store.js.map +0 -7
- package/dist/src/resonance-state.d.ts.map +0 -1
- package/dist/src/resonance-state.js.map +0 -7
- package/dist/src/retriever.d.ts.map +0 -1
- package/dist/src/retriever.js.map +0 -7
- package/dist/src/scopes.d.ts.map +0 -1
- package/dist/src/scopes.js.map +0 -7
- package/dist/src/self-improvement-files.d.ts.map +0 -1
- package/dist/src/self-improvement-files.js.map +0 -7
- package/dist/src/semantic-gate.d.ts.map +0 -1
- package/dist/src/semantic-gate.js.map +0 -7
- package/dist/src/session-recovery.d.ts.map +0 -1
- package/dist/src/session-recovery.js.map +0 -7
- package/dist/src/smart-extractor.d.ts.map +0 -1
- package/dist/src/smart-extractor.js.map +0 -7
- package/dist/src/smart-metadata.d.ts.map +0 -1
- package/dist/src/smart-metadata.js.map +0 -7
- package/dist/src/storage-adapter.d.ts.map +0 -1
- package/dist/src/storage-adapter.js.map +0 -7
- package/dist/src/store.d.ts.map +0 -1
- package/dist/src/store.js.map +0 -7
- package/dist/src/tier-manager.d.ts.map +0 -1
- package/dist/src/tier-manager.js.map +0 -7
- package/dist/src/tools.d.ts.map +0 -1
- package/dist/src/tools.js.map +0 -7
- package/dist/src/wal-recovery.d.ts.map +0 -1
- package/dist/src/wal-recovery.js.map +0 -7
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/smart-metadata.ts"],
|
|
4
|
-
"sourcesContent": ["// SPDX-License-Identifier: MIT\nimport type { MemoryCategory, MemoryTier } from \"./memory-categories.js\";\nimport type { DecayableMemory } from \"./decay-engine.js\";\n\ntype LegacyStoreCategory =\n | \"preference\"\n | \"fact\"\n | \"decision\"\n | \"entity\"\n | \"other\"\n | \"reflection\";\n\ntype EntryLike = {\n text?: string;\n category?: LegacyStoreCategory;\n importance?: number;\n timestamp?: number;\n metadata?: string;\n};\n\nexport interface SmartMemoryMetadata {\n l0_abstract: string;\n l1_overview: string;\n l2_content: string;\n memory_category: MemoryCategory;\n tier: MemoryTier;\n access_count: number;\n confidence: number;\n last_accessed_at: number;\n source_session?: string;\n /** Emotional salience score (0-1). Higher = more emotionally significant = decays slower.\n * Computed at store time via heuristic rules (zero LLM cost). */\n emotional_salience: number;\n [key: string]: unknown;\n}\n\nexport interface LifecycleMemory {\n id: string;\n importance: number;\n confidence: number;\n tier: MemoryTier;\n accessCount: number;\n createdAt: number;\n lastAccessedAt: number;\n emotionalSalience: number;\n}\n\nfunction clamp01(value: unknown, fallback: number): number {\n const n = typeof value === \"number\" ? value : Number(value);\n if (!Number.isFinite(n)) return fallback;\n return Math.min(1, Math.max(0, n));\n}\n\nfunction clampCount(value: unknown, fallback = 0): number {\n const n = typeof value === \"number\" ? value : Number(value);\n if (!Number.isFinite(n) || n < 0) return fallback;\n return Math.floor(n);\n}\n\n// ============================================================================\n// Emotional Salience \u2014 heuristic scoring (zero LLM cost)\n// ============================================================================\n\n/** High-salience signal patterns (decisions, strong emotions, firsts, money, people) */\nconst SALIENCE_BOOSTERS: Array<{ pattern: RegExp; boost: number }> = [\n // Decisions and commitments\n { pattern: /\\b(\u51B3\u5B9A|\u51B3\u7B56|confirmed|decided|commit|approved|\u6279\u4E86|\u62CD\u677F|\u5B9A\u4E86)\\b/i, boost: 0.3 },\n // Strong emotions\n { pattern: /\\b(\u9707\u60CA|\u60CA\u559C|\u6124\u6012|\u5931\u671B|\u5174\u594B|amazing|shocked|frustrated|excited|worried|\u62C5\u5FC3)\\b/i, boost: 0.25 },\n // First-time events\n { pattern: /\\b(\u7B2C\u4E00\u6B21|\u9996\u6B21|first time|first ever|\u4ECE\u672A|never before)\\b/i, boost: 0.25 },\n // Financial significance\n { pattern: /\\b(\\d+\u4E07|\\d+\u4EBF|\\$[\\d,.]+[MBK]|\u4F30\u503C|valuation|\u6295\u8D44|\u6301\u4ED3)\\b/i, boost: 0.2 },\n // People and relationships (user-configurable entity names)\n { pattern: /\\b(colleague|partner|mentor|friend|manager|teammate)\\b/i, boost: 0.15 },\n // Lessons learned / mistakes\n { pattern: /\\b(\u6559\u8BAD|\u8E29\u5751|pitfall|lesson|mistake|bug|\u6545\u969C|\u6302\u4E86|\u5D29\u4E86)\\b/i, boost: 0.2 },\n // Preferences and identity\n { pattern: /\\b(\u559C\u6B22|\u8BA8\u538C|\u504F\u597D|prefer|hate|love|always|never)\\b/i, boost: 0.15 },\n // Exclamation / emphasis (emotional weight)\n { pattern: /[!\uFF01]{2,}|\u203C\uFE0F|\u26A0\uFE0F|\uD83D\uDD34|\uD83D\uDC80/, boost: 0.1 },\n];\n\n/** Low-salience patterns (routine, technical noise) */\nconst SALIENCE_DAMPENERS: Array<{ pattern: RegExp; dampen: number }> = [\n { pattern: /\\b(heartbeat|HEARTBEAT_OK)\\b/i, dampen: 0.2 },\n { pattern: /\\b(cron|restart|gateway|status)\\b/i, dampen: 0.1 },\n { pattern: /\\b(debug|stack trace|npm|node_modules|\\.tsx?|\\.jsx?)\\b/i, dampen: 0.1 },\n { pattern: /^\\[?(Updated|Added|Removed|Fixed|Set)\\]?\\s.{0,30}$/i, dampen: 0.15 }, // short auto-generated entries only\n];\n\n/**\n * Compute emotional salience from text + category.\n * Returns 0-1. Higher = more emotionally charged / personally significant.\n * Pure heuristic, no LLM call.\n */\nexport function computeEmotionalSalience(\n text: string,\n category?: string,\n importance?: number,\n): number {\n let score = 0.35; // baseline \u2014 neutral memory\n\n // Category boost\n if (category === \"decision\") score += 0.15;\n if (category === \"preference\") score += 0.1;\n if (category === \"reflection\") score += 0.1;\n\n // Importance as a weak signal\n if (typeof importance === \"number\" && importance > 0.8) score += 0.1;\n if (typeof importance === \"number\" && importance > 0.9) score += 0.05;\n\n // Pattern matching\n for (const { pattern, boost } of SALIENCE_BOOSTERS) {\n if (pattern.test(text)) score += boost;\n }\n for (const { pattern, dampen } of SALIENCE_DAMPENERS) {\n if (pattern.test(text)) score -= dampen;\n }\n\n return Math.min(1, Math.max(0, score));\n}\n\n// ============================================================================\n// Emotion Calibration \u2014 rule-based post-processing for LLM valence\n// ============================================================================\n\n/** Strong emotion signal words (positive or negative) */\nconst STRONG_EMOTION_PATTERNS = [\n /\u592A\u597D\u4E86|\u592A\u68D2\u4E86|amazing|incredible|wonderful|fantastic|excellent/i,\n /terrible|horrible|awful|disgusting|devastating/i,\n /fuck|shit|damn|\u9760|\u5367\u69FD|\u6211\u53BB|\u5988\u7684/i,\n /\u54C8\u54C8\u54C8|lol|lmao|rofl|\uD83D\uDE02|\uD83E\uDD23/i,\n /[!\uFF01]{3,}/,\n /heartbroken|ecstatic|furious|thrilled|terrified/i,\n /\u5D29\u6E83|\u66B4\u6012|\u72C2\u559C|\u7EDD\u671B|\u9707\u60CA|\u5174\u594B\u6B7B\u4E86/i,\n];\n\n/** Factual / data-heavy text indicators */\nconst FACTUAL_PATTERNS = [\n /\u4F30\u503C|revenue|valuation|profit|loss|margin/i,\n /[$\uFFE5\u20AC\u00A3]/,\n /%/,\n];\n\n/**\n * Calibrate LLM-returned emotion valence with rule-based post-processing.\n *\n * Fixes two common LLM failure modes:\n * 1. Strong emotional text scored as neutral (0.4-0.6) \u2192 push toward extremes\n * 2. Pure factual/data text scored as emotional \u2192 compress toward neutral\n *\n * @param text - The memory text\n * @param rawValence - LLM-returned valence (0-1, 0.5 = neutral)\n * @returns Calibrated valence (0-1)\n */\nexport function calibrateEmotion(text: string, rawValence: number): number {\n if (!Number.isFinite(rawValence)) return 0.5;\n\n // Check for strong emotion signals\n const hasStrongEmotion = STRONG_EMOTION_PATTERNS.some(p => p.test(text));\n\n // Check if text is factual/data-heavy\n const digitChars = (text.match(/\\d/g) || []).length;\n const digitRatio = text.length > 0 ? digitChars / text.length : 0;\n const hasFactualSignals = digitRatio > 0.3 || FACTUAL_PATTERNS.some(p => p.test(text));\n\n let calibrated = rawValence;\n\n // Fix 1: Strong emotion + neutral valence \u2192 push to 0.3 or 0.7\n if (hasStrongEmotion && rawValence >= 0.4 && rawValence <= 0.6) {\n // Determine direction: below 0.5 \u2192 negative, above \u2192 positive\n calibrated = rawValence <= 0.5 ? 0.3 : 0.7;\n }\n\n // Fix 2: Factual text \u2192 compress to 0.45-0.55\n if (hasFactualSignals && !hasStrongEmotion) {\n if (calibrated < 0.45) calibrated = 0.45;\n if (calibrated > 0.55) calibrated = 0.55;\n }\n\n return Math.min(1, Math.max(0, calibrated));\n}\n\nfunction normalizeTier(value: unknown): MemoryTier {\n switch (value) {\n case \"core\":\n case \"working\":\n case \"peripheral\":\n return value;\n default:\n return \"working\";\n }\n}\n\nexport function reverseMapLegacyCategory(\n oldCategory: LegacyStoreCategory | undefined,\n text = \"\",\n): MemoryCategory {\n switch (oldCategory) {\n case \"preference\":\n return \"preferences\";\n case \"entity\":\n return \"entities\";\n case \"decision\":\n return \"events\";\n case \"other\":\n return \"patterns\";\n case \"fact\":\n if (\n /\\b(my |i am |i'm |name is |\u53EB\u6211|\u6211\u7684|\u6211\u662F)\\b/i.test(text) &&\n text.length < 200\n ) {\n return \"profile\";\n }\n return \"cases\";\n default:\n return \"patterns\";\n }\n}\n\nfunction defaultOverview(text: string): string {\n return `- ${text}`;\n}\n\nfunction normalizeText(value: unknown, fallback: string): string {\n return typeof value === \"string\" && value.trim() ? value.trim() : fallback;\n}\n\nexport function parseSmartMetadata(\n rawMetadata: string | undefined,\n entry: EntryLike = {},\n): SmartMemoryMetadata {\n let parsed: Record<string, unknown> = {};\n if (rawMetadata) {\n try {\n const obj = JSON.parse(rawMetadata);\n if (obj && typeof obj === \"object\") {\n parsed = obj as Record<string, unknown>;\n }\n } catch {\n parsed = {};\n }\n }\n\n const text = entry.text ?? \"\";\n const timestamp =\n typeof entry.timestamp === \"number\" && Number.isFinite(entry.timestamp)\n ? entry.timestamp\n : Date.now();\n\n const memoryCategory = reverseMapLegacyCategory(entry.category, text);\n const l0 = normalizeText(parsed.l0_abstract, text);\n const l2 = normalizeText(parsed.l2_content, text);\n const normalized: SmartMemoryMetadata = {\n ...parsed,\n l0_abstract: l0,\n l1_overview: normalizeText(parsed.l1_overview, defaultOverview(l0)),\n l2_content: l2,\n memory_category:\n typeof parsed.memory_category === \"string\"\n ? (parsed.memory_category as MemoryCategory)\n : memoryCategory,\n tier: normalizeTier(parsed.tier),\n access_count: clampCount(parsed.access_count, 0),\n confidence: clamp01(parsed.confidence, 0.7),\n last_accessed_at: clampCount(parsed.last_accessed_at, timestamp),\n source_session:\n typeof parsed.source_session === \"string\" ? parsed.source_session : undefined,\n emotional_salience: clamp01(\n parsed.emotional_salience,\n computeEmotionalSalience(text, entry.category, entry.importance),\n ),\n };\n\n return normalized;\n}\n\nexport function buildSmartMetadata(\n entry: EntryLike,\n patch: Partial<SmartMemoryMetadata> = {},\n): SmartMemoryMetadata {\n const base = parseSmartMetadata(entry.metadata, entry);\n const text = entry.text ?? \"\";\n\n // Calibrate emotional salience: fix LLM mis-scoring of strong emotions / factual text\n const rawSalience = clamp01(\n patch.emotional_salience ?? base.emotional_salience,\n base.emotional_salience,\n );\n const calibratedSalience = calibrateEmotion(text, rawSalience);\n\n return {\n ...base,\n ...patch,\n l0_abstract: normalizeText(patch.l0_abstract, base.l0_abstract),\n l1_overview: normalizeText(patch.l1_overview, base.l1_overview),\n l2_content: normalizeText(patch.l2_content, base.l2_content),\n memory_category:\n typeof patch.memory_category === \"string\"\n ? patch.memory_category\n : base.memory_category,\n tier: normalizeTier(patch.tier ?? base.tier),\n access_count: clampCount(patch.access_count, base.access_count),\n confidence: clamp01(patch.confidence, base.confidence),\n last_accessed_at: clampCount(\n patch.last_accessed_at,\n base.last_accessed_at || entry.timestamp || Date.now(),\n ),\n source_session:\n typeof patch.source_session === \"string\"\n ? patch.source_session\n : base.source_session,\n emotional_salience: calibratedSalience,\n };\n}\n\n// Metadata array size caps \u2014 prevent unbounded JSON growth\nconst MAX_SOURCES = 20;\nconst MAX_HISTORY = 50;\nconst MAX_RELATIONS = 16;\n\nexport function stringifySmartMetadata(\n metadata: SmartMemoryMetadata | Record<string, unknown>,\n): string {\n const capped = { ...metadata } as Record<string, unknown>;\n\n // Cap array fields to prevent metadata bloat\n if (Array.isArray(capped.sources) && capped.sources.length > MAX_SOURCES) {\n capped.sources = capped.sources.slice(-MAX_SOURCES); // keep most recent\n }\n if (Array.isArray(capped.history) && capped.history.length > MAX_HISTORY) {\n capped.history = capped.history.slice(-MAX_HISTORY);\n }\n if (Array.isArray(capped.relations) && capped.relations.length > MAX_RELATIONS) {\n capped.relations = capped.relations.slice(0, MAX_RELATIONS);\n }\n\n return JSON.stringify(capped);\n}\n\nexport function toLifecycleMemory(\n id: string,\n entry: EntryLike,\n): LifecycleMemory {\n const metadata = parseSmartMetadata(entry.metadata, entry);\n const createdAt =\n typeof entry.timestamp === \"number\" && Number.isFinite(entry.timestamp)\n ? entry.timestamp\n : Date.now();\n\n return {\n id,\n importance:\n typeof entry.importance === \"number\" && Number.isFinite(entry.importance)\n ? entry.importance\n : 0.7,\n confidence: metadata.confidence,\n tier: metadata.tier,\n accessCount: metadata.access_count,\n createdAt,\n lastAccessedAt: metadata.last_accessed_at || createdAt,\n emotionalSalience: metadata.emotional_salience,\n };\n}\n\n/**\n * Parse a memory entry into both a DecayableMemory (for the decay engine)\n * and the raw SmartMemoryMetadata (for in-place mutation before write-back).\n */\nexport function getDecayableFromEntry(\n entry: EntryLike & { id?: string },\n): { memory: DecayableMemory; meta: SmartMemoryMetadata } {\n const meta = parseSmartMetadata(entry.metadata, entry);\n const createdAt =\n typeof entry.timestamp === \"number\" && Number.isFinite(entry.timestamp)\n ? entry.timestamp\n : Date.now();\n\n const memory: DecayableMemory = {\n id: (entry as { id?: string }).id ?? \"\",\n importance:\n typeof entry.importance === \"number\" && Number.isFinite(entry.importance)\n ? entry.importance\n : 0.7,\n confidence: meta.confidence,\n tier: meta.tier,\n accessCount: meta.access_count,\n createdAt,\n lastAccessedAt: meta.last_accessed_at || createdAt,\n emotionalSalience: meta.emotional_salience,\n };\n\n return { memory, meta };\n}\n\n// ============================================================================\n// Contextual Support \u2014 optional extension to SmartMemoryMetadata\n// ============================================================================\n\n/** Predefined context vocabulary for support slices */\nexport const SUPPORT_CONTEXT_VOCABULARY = [\n \"general\", \"morning\", \"afternoon\", \"evening\", \"night\",\n \"weekday\", \"weekend\", \"work\", \"leisure\",\n \"summer\", \"winter\", \"travel\",\n] as const;\n\nexport type SupportContext = (typeof SUPPORT_CONTEXT_VOCABULARY)[number] | string;\n\n/** Max number of context slices per memory to prevent metadata bloat */\nexport const MAX_SUPPORT_SLICES = 8;\n\n/** A single context-specific support slice */\nexport interface ContextualSupport {\n context: SupportContext;\n confirmations: number;\n contradictions: number;\n strength: number; // confirmations / (confirmations + contradictions)\n last_observed_at: number;\n}\n\n/** V2 support info with per-context slices */\nexport interface SupportInfoV2 {\n global_strength: number; // weighted average across all slices\n total_observations: number; // sum of all confirmations + contradictions\n slices: ContextualSupport[];\n}\n\n/**\n * Normalize a raw context label to a canonical context.\n * Maps common variants and falls back to \"general\".\n */\nexport function normalizeContext(raw: string | undefined): SupportContext {\n if (!raw || !raw.trim()) return \"general\";\n const lower = raw.trim().toLowerCase();\n\n // Direct vocabulary match\n if ((SUPPORT_CONTEXT_VOCABULARY as readonly string[]).includes(lower)) {\n return lower as SupportContext;\n }\n\n // Common Chinese/English mappings\n const aliases: Record<string, SupportContext> = {\n \"\u65E9\u4E0A\": \"morning\", \"\u4E0A\u5348\": \"morning\", \"\u65E9\u6668\": \"morning\",\n \"\u4E0B\u5348\": \"afternoon\", \"\u508D\u665A\": \"evening\", \"\u665A\u4E0A\": \"evening\",\n \"\u6DF1\u591C\": \"night\", \"\u591C\u665A\": \"night\", \"\u51CC\u6668\": \"night\",\n \"\u5DE5\u4F5C\u65E5\": \"weekday\", \"\u5E73\u65F6\": \"weekday\",\n \"\u5468\u672B\": \"weekend\", \"\u5047\u65E5\": \"weekend\", \"\u4F11\u606F\u65E5\": \"weekend\",\n \"\u5DE5\u4F5C\": \"work\", \"\u4E0A\u73ED\": \"work\", \"\u529E\u516C\": \"work\",\n \"\u4F11\u95F2\": \"leisure\", \"\u653E\u677E\": \"leisure\", \"\u4F11\u606F\": \"leisure\",\n \"\u590F\u5929\": \"summer\", \"\u590F\u5B63\": \"summer\",\n \"\u51AC\u5929\": \"winter\", \"\u51AC\u5B63\": \"winter\",\n \"\u65C5\u884C\": \"travel\", \"\u51FA\u5DEE\": \"travel\", \"\u65C5\u6E38\": \"travel\",\n };\n\n return aliases[lower] || lower; // keep as custom context if not mapped\n}\n\n/**\n * Parse support_info from metadata JSON. Handles V1 (flat) \u2192 V2 (sliced) migration.\n */\nexport function parseSupportInfo(raw: unknown): SupportInfoV2 {\n const defaultV2: SupportInfoV2 = {\n global_strength: 0.5,\n total_observations: 0,\n slices: [],\n };\n\n if (!raw || typeof raw !== \"object\") return defaultV2;\n const obj = raw as Record<string, unknown>;\n\n // V2 format: has slices array\n if (Array.isArray(obj.slices)) {\n return {\n global_strength: typeof obj.global_strength === \"number\" ? obj.global_strength : 0.5,\n total_observations: typeof obj.total_observations === \"number\" ? obj.total_observations : 0,\n slices: (obj.slices as Record<string, unknown>[]).filter(\n s => s && typeof s.context === \"string\",\n ).map(s => ({\n context: String(s.context),\n confirmations: typeof s.confirmations === \"number\" && s.confirmations >= 0 ? s.confirmations : 0,\n contradictions: typeof s.contradictions === \"number\" && s.contradictions >= 0 ? s.contradictions : 0,\n strength: typeof s.strength === \"number\" && s.strength >= 0 && s.strength <= 1 ? s.strength : 0.5,\n last_observed_at: typeof s.last_observed_at === \"number\" ? s.last_observed_at : Date.now(),\n })),\n };\n }\n\n // V1 format: flat { confirmations, contradictions, strength }\n const conf = typeof obj.confirmations === \"number\" ? obj.confirmations : 0;\n const contra = typeof obj.contradictions === \"number\" ? obj.contradictions : 0;\n const total = conf + contra;\n if (total === 0) return defaultV2;\n\n return {\n global_strength: total > 0 ? conf / total : 0.5,\n total_observations: total,\n slices: [{\n context: \"general\",\n confirmations: conf,\n contradictions: contra,\n strength: total > 0 ? conf / total : 0.5,\n last_observed_at: Date.now(),\n }],\n };\n}\n\n/**\n * Update support stats for a specific context.\n * Returns a new SupportInfoV2 with the updated slice.\n */\nexport function updateSupportStats(\n existing: SupportInfoV2,\n contextLabel: string | undefined,\n event: \"support\" | \"contradict\",\n): SupportInfoV2 {\n const ctx = normalizeContext(contextLabel);\n const base = { ...existing, slices: [...existing.slices.map(s => ({ ...s }))] };\n\n // Find or create the context slice\n let slice = base.slices.find(s => s.context === ctx);\n if (!slice) {\n slice = { context: ctx, confirmations: 0, contradictions: 0, strength: 0.5, last_observed_at: Date.now() };\n base.slices.push(slice);\n }\n\n // Update slice\n if (event === \"support\") slice.confirmations++;\n else slice.contradictions++;\n const sliceTotal = slice.confirmations + slice.contradictions;\n slice.strength = sliceTotal > 0 ? slice.confirmations / sliceTotal : 0.5;\n slice.last_observed_at = Date.now();\n\n // Cap slices (keep most recently observed, but preserve dropped evidence).\n // NOTE: Evidence from slices dropped in *previous* updates is already baked\n // into total_observations/global_strength, so those values may drift slightly\n // over many truncation cycles. This is an accepted trade-off for bounded JSON size.\n let slices = base.slices;\n let droppedConf = 0, droppedContra = 0;\n if (slices.length > MAX_SUPPORT_SLICES) {\n slices = slices\n .sort((a, b) => b.last_observed_at - a.last_observed_at);\n const dropped = slices.slice(MAX_SUPPORT_SLICES);\n for (const d of dropped) {\n droppedConf += d.confirmations;\n droppedContra += d.contradictions;\n }\n slices = slices.slice(0, MAX_SUPPORT_SLICES);\n }\n\n // Recompute global strength including evidence from dropped slices\n let totalConf = droppedConf, totalContra = droppedContra;\n for (const s of slices) {\n totalConf += s.confirmations;\n totalContra += s.contradictions;\n }\n const totalObs = totalConf + totalContra;\n const global_strength = totalObs > 0 ? totalConf / totalObs : 0.5;\n\n return { global_strength, total_observations: totalObs, slices };\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"storage-adapter.d.ts","sourceRoot":"","sources":["../../src/storage-adapter.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAIH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvC;;;;OAIG;IACH,WAAW,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErD;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5C;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExD;;;OAGG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtC;;;OAGG;IACH,YAAY,CACV,MAAM,EAAE,MAAM,EAAE,EAChB,KAAK,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAE3B;;;OAGG;IACH,cAAc,CACZ,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAE3B;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAEtD;;OAEG;IACH,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAExC;;OAEG;IACH,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAErC;;OAEG;IACH,iBAAiB,IAAI,OAAO,CAAC;IAE7B;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAID,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,cAAc,CAAC;AAIlF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAE3E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,cAAc,CAU5F;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAEvC"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/storage-adapter.ts"],
|
|
4
|
-
"sourcesContent": ["// SPDX-License-Identifier: MIT\n/**\n * StorageAdapter \u2014 Abstract interface for vector storage backends.\n *\n * Mnemo ships with LanceDB as the default adapter.\n * Implement this interface to add support for other backends\n * (Qdrant, Chroma, Milvus, Pinecone, PGVector, etc.)\n */\n\n// \u2500\u2500 Types \u2500\u2500\n\nexport interface MemoryRecord {\n id: string;\n text: string;\n vector: number[];\n timestamp: number;\n scope: string;\n importance: number;\n category: string;\n metadata: string;\n [key: string]: unknown;\n}\n\nexport interface SearchResult {\n record: MemoryRecord;\n score: number;\n}\n\nexport interface QueryOptions {\n where?: string;\n select?: string[];\n limit?: number;\n offset?: number;\n}\n\n// \u2500\u2500 Interface \u2500\u2500\n\nexport interface StorageAdapter {\n /** Adapter name for logging and diagnostics */\n readonly name: string;\n\n /**\n * Connect to the storage backend.\n * @param dbPath - path or connection string\n */\n connect(dbPath: string): Promise<void>;\n\n /**\n * Ensure the memories table exists with proper schema.\n * Creates the table if it doesn't exist, opens it if it does.\n * @param vectorDimensions - embedding vector dimensions (e.g. 1024)\n */\n ensureTable(vectorDimensions: number): Promise<void>;\n\n /**\n * Insert one or more records.\n */\n add(records: MemoryRecord[]): Promise<void>;\n\n /**\n * Update a record by ID. Typically delete + re-insert.\n */\n update(id: string, record: MemoryRecord): Promise<void>;\n\n /**\n * Delete records matching a filter expression.\n * @param filter - SQL-like filter string, e.g. \"id = 'abc'\"\n */\n delete(filter: string): Promise<void>;\n\n /**\n * Vector similarity search.\n * @returns results sorted by descending similarity score (0-1)\n */\n vectorSearch(\n vector: number[],\n limit: number,\n minScore?: number,\n scopeFilter?: string[],\n ): Promise<SearchResult[]>;\n\n /**\n * Full-text (BM25) search.\n * @returns results sorted by descending relevance score\n */\n fullTextSearch(\n query: string,\n limit: number,\n scopeFilter?: string[],\n ): Promise<SearchResult[]>;\n\n /**\n * General-purpose query with optional filter, select, limit.\n */\n query(options: QueryOptions): Promise<MemoryRecord[]>;\n\n /**\n * Count records matching an optional filter.\n */\n count(filter?: string): Promise<number>;\n\n /**\n * Ensure full-text search index exists on the text field.\n */\n ensureFullTextIndex(): Promise<void>;\n\n /**\n * Check if full-text search is supported and initialized.\n */\n hasFullTextSearch(): boolean;\n\n /**\n * Close the connection / cleanup resources.\n */\n close(): Promise<void>;\n}\n\n// \u2500\u2500 Factory \u2500\u2500\n\nexport type AdapterFactory = (config?: Record<string, unknown>) => StorageAdapter;\n\nconst _registry = new Map<string, AdapterFactory>();\n\n/**\n * Register a storage adapter backend.\n * @example registerAdapter(\"qdrant\", (config) => new QdrantAdapter(config))\n */\nexport function registerAdapter(name: string, factory: AdapterFactory): void {\n _registry.set(name, factory);\n}\n\n/**\n * Create a storage adapter by name.\n * Falls back to LanceDB if name is not registered.\n */\nexport function createAdapter(name: string, config?: Record<string, unknown>): StorageAdapter {\n const factory = _registry.get(name);\n if (!factory) {\n throw new Error(\n `Storage adapter \"${name}\" not found. ` +\n `Available: ${[..._registry.keys()].join(\", \") || \"(none)\"}. ` +\n `Did you forget to call registerAdapter()?`\n );\n }\n return factory(config);\n}\n\n/**\n * List all registered adapter names.\n */\nexport function listAdapters(): string[] {\n return [..._registry.keys()];\n}\n"],
|
|
5
|
-
"mappings": "AAyHA,MAAM,YAAY,oBAAI,IAA4B;AAM3C,SAAS,gBAAgB,MAAc,SAA+B;AAC3E,YAAU,IAAI,MAAM,OAAO;AAC7B;AAMO,SAAS,cAAc,MAAc,QAAkD;AAC5F,QAAM,UAAU,UAAU,IAAI,IAAI;AAClC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR,oBAAoB,IAAI,2BACV,CAAC,GAAG,UAAU,KAAK,CAAC,EAAE,KAAK,IAAI,KAAK,QAAQ;AAAA,IAE5D;AAAA,EACF;AACA,SAAO,QAAQ,MAAM;AACvB;AAKO,SAAS,eAAyB;AACvC,SAAO,CAAC,GAAG,UAAU,KAAK,CAAC;AAC7B;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
package/dist/src/store.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/store.ts"],"names":[],"mappings":"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"}
|
package/dist/src/store.js.map
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/store.ts"],
|
|
4
|
-
"sourcesContent": ["// SPDX-License-Identifier: MIT\n/**\n * LanceDB Storage Layer with Multi-Scope Support\n */\n\nimport type * as LanceDB from \"@lancedb/lancedb\";\nimport { randomUUID } from \"node:crypto\";\nimport {\n existsSync,\n accessSync,\n constants,\n mkdirSync,\n realpathSync,\n lstatSync,\n} from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { buildSmartMetadata, parseSmartMetadata, stringifySmartMetadata } from \"./smart-metadata.js\";\nimport type { SemanticGate } from \"./semantic-gate.js\";\nimport { requirePro } from \"./license.js\";\nimport { log } from \"./logger.js\";\n\n// Pro: Audit log \u2014 record all CRUD operations for GDPR/compliance\n// TODO: type these with actual audit function signatures from audit-log.ts\nlet _auditCreate: ((...args: unknown[]) => void) | null = null;\nlet _auditUpdate: ((...args: unknown[]) => void) | null = null;\nlet _auditDelete: ((...args: unknown[]) => void) | null = null;\nlet _auditExpire: ((...args: unknown[]) => void) | null = null;\n\nif (requirePro(\"audit-log\")) {\n import(\"./audit-log.js\").then((mod) => {\n _auditCreate = mod.auditCreate;\n _auditUpdate = mod.auditUpdate;\n _auditDelete = mod.auditDelete;\n _auditExpire = mod.auditExpire;\n }).catch(() => {});\n}\n\n// Pro: WAL (Write-Ahead Log) \u2014 graceful degradation without license\n// TODO: type these with actual WAL function signatures from wal-recovery.ts\nlet walAppend: ((...args: unknown[]) => Promise<void>) | null = null;\nlet walMarkCommitted: ((...args: unknown[]) => Promise<void>) | null = null;\nlet walMarkFailed: ((...args: unknown[]) => Promise<void>) | null = null;\n\nif (requirePro(\"wal\")) {\n import(\"./wal-recovery.js\").then((mod) => {\n walAppend = mod.walAppend;\n walMarkCommitted = mod.walMarkCommitted;\n walMarkFailed = mod.walMarkFailed;\n }).catch(() => {});\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface MemoryEntry {\n id: string;\n text: string;\n vector: number[];\n category: \"preference\" | \"fact\" | \"decision\" | \"entity\" | \"other\" | \"reflection\";\n scope: string;\n importance: number;\n timestamp: number;\n metadata?: string; // JSON string for extensible metadata\n}\n\nexport interface MemorySearchResult {\n entry: MemoryEntry;\n score: number;\n}\n\nexport interface StoreConfig {\n dbPath: string;\n vectorDim: number;\n /** Enable near-duplicate detection before writing (default: true) */\n deduplication?: boolean;\n /** Enable semantic noise gate to filter fragments (default: true) */\n semanticGate?: boolean;\n /** Storage backend: \"lancedb\" (default), \"qdrant\", \"chroma\", \"pgvector\" */\n storageBackend?: string;\n /** Backend-specific config (url, connectionString, etc.) */\n storageConfig?: Record<string, unknown>;\n}\n\nconst DEDUP_SIMILARITY_THRESHOLD = 0.92;\nconst CONFLICT_SIMILARITY_THRESHOLD = 0.70;\n\nexport interface MetadataPatch {\n [key: string]: unknown;\n}\n\n// ============================================================================\n// Storage Adapter Support (multi-backend)\n// ============================================================================\n\nimport type { StorageAdapter } from \"./storage-adapter.js\";\nimport { createAdapter, listAdapters } from \"./storage-adapter.js\";\n\n// Auto-register adapters on first import\nlet _adaptersLoaded = false;\nasync function ensureAdaptersLoaded(): Promise<void> {\n if (_adaptersLoaded) return;\n _adaptersLoaded = true;\n // Dynamic imports \u2014 only loads the adapter that's actually needed\n const dbg = !!process.env.MNEMO_DEBUG;\n try { await import(\"./adapters/lancedb.js\"); } catch (e) { if (dbg) log.debug(\"adapter lancedb not available:\", e); }\n try { await import(\"./adapters/qdrant.js\"); } catch (e) { if (dbg) log.debug(\"adapter qdrant not available:\", e); }\n try { await import(\"./adapters/chroma.js\"); } catch (e) { if (dbg) log.debug(\"adapter chroma not available:\", e); }\n try { await import(\"./adapters/pgvector.js\"); } catch (e) { if (dbg) log.debug(\"adapter pgvector not available:\", e); }\n}\n\n// ============================================================================\n// LanceDB Dynamic Import (legacy path \u2014 used when storageBackend is unset or \"lancedb\")\n// ============================================================================\n\nlet lancedbImportPromise: Promise<typeof import(\"@lancedb/lancedb\")> | null =\n null;\n\nexport const loadLanceDB = async (): Promise<\n typeof import(\"@lancedb/lancedb\")\n> => {\n if (!lancedbImportPromise) {\n lancedbImportPromise = import(\"@lancedb/lancedb\");\n }\n try {\n return await lancedbImportPromise;\n } catch (err) {\n throw new Error(\n `mnemo: failed to load LanceDB. ${String(err)}`,\n { cause: err },\n );\n }\n};\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\nfunction clampInt(value: number, min: number, max: number): number {\n if (!Number.isFinite(value)) return min;\n return Math.min(max, Math.max(min, Math.floor(value)));\n}\n\n/**\n * Sanitize a string for use in SQL WHERE clauses.\n * Strips everything except alphanumeric, dash, underscore, dot, colon, and space.\n * This is stricter than SQL escaping \u2014 it prevents injection by allowlist.\n */\nfunction escapeSqlLiteral(value: string): string {\n if (typeof value !== \"string\") return \"\";\n // Allowlist: only safe chars for IDs, scopes, categories\n return value.replace(/[^a-zA-Z0-9\\-_.:@ \\u4e00-\\u9fff\\u3400-\\u4dbf]/g, \"\");\n}\n\nfunction normalizeSearchText(value: string): string {\n return value.toLowerCase().trim();\n}\n\nfunction scoreLexicalHit(query: string, candidates: Array<{ text: string; weight: number }>): number {\n const normalizedQuery = normalizeSearchText(query);\n if (!normalizedQuery) return 0;\n\n let score = 0;\n for (const candidate of candidates) {\n const normalized = normalizeSearchText(candidate.text);\n if (!normalized) continue;\n if (normalized.includes(normalizedQuery)) {\n score = Math.max(score, Math.min(0.95, 0.72 + normalizedQuery.length * 0.02) * candidate.weight);\n }\n }\n\n return score;\n}\n\n// ============================================================================\n// Storage Path Validation\n// ============================================================================\n\n/**\n * Validate and prepare the storage directory before LanceDB connection.\n * Resolves symlinks, creates missing directories, and checks write permissions.\n * Returns the resolved absolute path on success, or throws a descriptive error.\n */\nexport function validateStoragePath(dbPath: string): string {\n let resolvedPath = dbPath;\n\n // Resolve symlinks (including dangling symlinks)\n try {\n const stats = lstatSync(dbPath);\n if (stats.isSymbolicLink()) {\n try {\n resolvedPath = realpathSync(dbPath);\n } catch (err: unknown) {\n const e = err as NodeJS.ErrnoException;\n throw new Error(\n `dbPath \"${dbPath}\" is a symlink whose target does not exist.\\n` +\n ` Fix: Create the target directory, or update the symlink to point to a valid path.\\n` +\n ` Details: ${e.code || \"\"} ${e.message}`,\n );\n }\n }\n } catch (err: unknown) {\n const e = err as NodeJS.ErrnoException;\n // Missing path is OK (it will be created below)\n if (e?.code === \"ENOENT\") {\n // no-op\n } else if (\n typeof e?.message === \"string\" &&\n e.message.includes(\"symlink whose target does not exist\")\n ) {\n throw err;\n } else {\n // Other lstat failures \u2014 continue with original path\n }\n }\n\n // Create directory if it doesn't exist\n if (!existsSync(resolvedPath)) {\n try {\n mkdirSync(resolvedPath, { recursive: true });\n } catch (err: unknown) {\n const e = err as NodeJS.ErrnoException;\n throw new Error(\n `Failed to create dbPath directory \"${resolvedPath}\".\\n` +\n ` Fix: Ensure the parent directory \"${dirname(resolvedPath)}\" exists and is writable,\\n` +\n ` or create it manually: mkdir -p \"${resolvedPath}\"\\n` +\n ` Details: ${e.code || \"\"} ${e.message}`,\n );\n }\n }\n\n // Check write permissions\n try {\n accessSync(resolvedPath, constants.W_OK);\n } catch (err: unknown) {\n const e = err as NodeJS.ErrnoException;\n throw new Error(\n `dbPath directory \"${resolvedPath}\" is not writable.\\n` +\n ` Fix: Check permissions with: ls -la \"${dirname(resolvedPath)}\"\\n` +\n ` Or grant write access: chmod u+w \"${resolvedPath}\"\\n` +\n ` Details: ${e.code || \"\"} ${e.message}`,\n );\n }\n\n return resolvedPath;\n}\n\n// ============================================================================\n// Memory Store\n// ============================================================================\n\nconst TABLE_NAME = \"memories\";\n\nexport class MemoryStore {\n private db: LanceDB.Connection | null = null;\n private table: LanceDB.Table | null = null;\n private initPromise: Promise<void> | null = null;\n private ftsIndexCreated = false;\n private updateQueue: Promise<void> = Promise.resolve();\n private semanticGateInstance: SemanticGate | null = null;\n\n /** When using a non-LanceDB adapter, this holds the active adapter instance */\n private _adapter: StorageAdapter | null = null;\n\n /** True when using the adapter path (non-LanceDB backends) */\n get usingAdapter(): boolean { return this._adapter !== null; }\n\n constructor(private readonly config: StoreConfig) { }\n\n /** Inject a SemanticGate instance (created externally with an Embedder). */\n setSemanticGate(gate: SemanticGate): void {\n this.semanticGateInstance = gate;\n }\n\n get dbPath(): string {\n return this.config.dbPath;\n }\n\n /** Get the active adapter (null if using legacy LanceDB path) */\n get adapter(): StorageAdapter | null {\n return this._adapter;\n }\n\n /** Whether BM25 full-text search is available */\n get hasFtsSupport(): boolean {\n if (this._adapter) return this._adapter.hasFullTextSearch();\n return this.ftsIndexCreated;\n }\n\n private async ensureInitialized(): Promise<void> {\n if (this.table || this._adapter) {\n return;\n }\n if (this.initPromise) {\n return this.initPromise;\n }\n\n this.initPromise = this.doInitialize().catch((err) => {\n this.initPromise = null;\n throw err;\n });\n return this.initPromise;\n }\n\n private async doInitialize(): Promise<void> {\n // \u2500\u2500 Adapter path: non-LanceDB backends (qdrant, chroma, pgvector) \u2500\u2500\n const backend = this.config.storageBackend;\n if (backend && backend !== \"lancedb\") {\n await ensureAdaptersLoaded();\n const available = listAdapters();\n if (!available.includes(backend)) {\n throw new Error(\n `Storage backend \"${backend}\" not available. Installed: ${available.join(\", \")}. ` +\n `Check that the adapter is properly imported.`\n );\n }\n this._adapter = createAdapter(backend, this.config.storageConfig);\n await this._adapter.connect(this.config.dbPath);\n await this._adapter.ensureTable(this.config.vectorDim);\n this.ftsIndexCreated = this._adapter.hasFullTextSearch();\n return; // Skip LanceDB initialization\n }\n\n // \u2500\u2500 Legacy LanceDB path (default) \u2500\u2500\n const lancedb = await loadLanceDB();\n\n let db: LanceDB.Connection;\n try {\n db = await lancedb.connect(this.config.dbPath);\n } catch (err: unknown) {\n const e = err as NodeJS.ErrnoException;\n const code = e.code || \"\";\n const message = e.message || String(err);\n throw new Error(\n `Failed to open LanceDB at \"${this.config.dbPath}\": ${code} ${message}\\n` +\n ` Fix: Verify the path exists and is writable. Check parent directory permissions.`,\n );\n }\n\n let table: LanceDB.Table;\n\n // Idempotent table init: try openTable first, create only if missing,\n // and handle the race where tableNames() misses an existing table but\n // createTable then sees it (LanceDB eventual consistency).\n try {\n table = await db.openTable(TABLE_NAME);\n\n // Check if we need to add scope column for backward compatibility\n try {\n const sample = await table.query().limit(1).toArray();\n if (sample.length > 0 && !(\"scope\" in sample[0])) {\n log.warn(\n \"Adding scope column for backward compatibility with existing data\",\n );\n }\n } catch (err) {\n log.warn(\"Could not check table schema:\", err);\n }\n } catch (_openErr) {\n // Table doesn't exist yet \u2014 create it\n const schemaEntry: MemoryEntry = {\n id: \"__schema__\",\n text: \"\",\n vector: Array.from({ length: this.config.vectorDim }).fill(\n 0,\n ) as number[],\n category: \"other\",\n scope: \"global\",\n importance: 0,\n timestamp: 0,\n metadata: \"{}\",\n };\n\n try {\n table = await db.createTable(TABLE_NAME, [schemaEntry]);\n await table.delete('id = \"__schema__\"');\n } catch (createErr) {\n // Race: another caller (or eventual consistency) created the table\n // between our failed openTable and this createTable \u2014 just open it.\n if (String(createErr).includes(\"already exists\")) {\n table = await db.openTable(TABLE_NAME);\n } else {\n throw createErr;\n }\n }\n }\n\n // Validate vector dimensions\n // Note: LanceDB returns Arrow Vector objects, not plain JS arrays.\n // Array.isArray() returns false for Arrow Vectors, so use .length instead.\n const sample = await table.query().limit(1).toArray();\n if (sample.length > 0 && sample[0]?.vector?.length) {\n const existingDim = sample[0].vector.length;\n if (existingDim !== this.config.vectorDim) {\n throw new Error(\n `Vector dimension mismatch: table=${existingDim}, config=${this.config.vectorDim}. Create a new table/dbPath or set matching embedding.dimensions.`,\n );\n }\n }\n\n // Create FTS index for BM25 search (graceful fallback if unavailable)\n try {\n await this.createFtsIndex(table);\n this.ftsIndexCreated = true;\n } catch (err) {\n log.warn(\n \"Failed to create FTS index, falling back to vector-only search:\",\n err,\n );\n this.ftsIndexCreated = false;\n }\n\n this.db = db;\n this.table = table;\n }\n\n private async createFtsIndex(table: LanceDB.Table): Promise<void> {\n try {\n // Check if FTS index already exists\n const indices = await table.listIndices();\n const hasFtsIndex = indices?.some(\n // TODO: type this \u2014 LanceDB index type lacks proper typings for indexType/columns\n (idx: any) => idx.indexType === \"FTS\" || idx.columns?.includes(\"text\"),\n );\n\n if (!hasFtsIndex) {\n // LanceDB @lancedb/lancedb >=0.26: use Index.fts() config\n const lancedb = await loadLanceDB();\n await table.createIndex(\"text\", {\n // TODO: type this \u2014 LanceDB dynamic import doesn't expose Index type\n config: (lancedb as any).Index.fts(),\n });\n }\n } catch (err) {\n throw new Error(\n `FTS index creation failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n async store(\n entry: Omit<MemoryEntry, \"id\" | \"timestamp\">,\n ): Promise<MemoryEntry> {\n await this.ensureInitialized();\n\n // \u2500\u2500 Step 0: Semantic noise gate (before dedup) \u2500\u2500\n if (this.config.semanticGate !== false && this.semanticGateInstance) {\n try {\n const passed = await this.semanticGateInstance.shouldPass(entry.vector, entry.text);\n if (!passed) {\n // Return a synthetic entry with a marker id so callers know it was filtered\n return {\n ...entry,\n id: \"__filtered__\",\n timestamp: Date.now(),\n metadata: entry.metadata || \"{}\",\n };\n }\n } catch {\n // Gate failure \u2192 pass through\n }\n }\n\n // \u2500\u2500 Step 1: Near-duplicate detection \u2500\u2500\n if (this.config.deduplication !== false && entry.vector && entry.vector.length > 0) {\n try {\n const scopeFilter = entry.scope ? [entry.scope] : undefined;\n const similar = await this.vectorSearch(entry.vector, 3, 0.3, scopeFilter);\n\n for (const match of similar) {\n // Convert LanceDB distance-based score to cosine similarity\n // vectorSearch returns score = 1 / (1 + distance), so:\n // cosine_similarity \u2248 1 - distance = (2*score - 1) / score ... but simpler:\n // For cosine distance: similarity = 1 - distance\n // score = 1/(1+d) \u2192 d = 1/score - 1 \u2192 similarity = 1 - d = 2 - 1/score\n const cosineSim = 2 - 1 / match.score;\n if (cosineSim > DEDUP_SIMILARITY_THRESHOLD) {\n // Duplicate found \u2014 update existing entry instead of creating new\n const existingMeta = parseSmartMetadata(match.entry.metadata, match.entry);\n const accessCount = (existingMeta.access_count ?? 0) + 1;\n\n const updates: {\n text?: string;\n importance?: number;\n metadata?: string;\n } = {};\n\n // If new text is longer or importance is higher, update\n if (entry.text.length > match.entry.text.length) {\n updates.text = entry.text;\n }\n if (entry.importance > match.entry.importance) {\n updates.importance = entry.importance;\n }\n\n // Always update accessCount and updatedAt\n const patchedMeta = {\n ...existingMeta,\n access_count: accessCount,\n updatedAt: Date.now(),\n };\n updates.metadata = stringifySmartMetadata(patchedMeta);\n\n await this.update(match.entry.id, updates, scopeFilter);\n\n // Return existing entry id so caller knows dedup happened\n return {\n ...match.entry,\n id: match.entry.id,\n timestamp: match.entry.timestamp,\n metadata: updates.metadata,\n };\n }\n }\n } catch {\n // Dedup failure \u2192 proceed with normal write\n }\n }\n\n // \u2500\u2500 Step 1b: Conflict detection (mid-similarity range) \u2500\u2500\n // If the new entry is similar but not identical to an existing one,\n // check if it's a contradiction/update and demote the old entry.\n // Search without scope filter to catch conflicts across scopes.\n if (this.config.deduplication !== false && entry.vector && entry.vector.length > 0) {\n try {\n const similar = await this.vectorSearch(entry.vector, 3, 0.3);\n\n for (const match of similar) {\n const cosineSim = 2 - 1 / match.score;\n if (cosineSim > CONFLICT_SIMILARITY_THRESHOLD && cosineSim <= DEDUP_SIMILARITY_THRESHOLD) {\n // Mid-range similarity: might be a contradiction or update\n // Heuristic: if both texts are about the same topic but have different\n // values/numbers/states, it's likely a contradiction\n const oldText = match.entry.text || \"\";\n const newText = entry.text || \"\";\n\n // Quick contradiction signals:\n // 1. Both mention the same entity but with different numbers\n // 2. Negation patterns (\u4E0D/\u6CA1/no/not + similar keywords)\n // 3. New text explicitly says \"changed to\" / \"\u6539\u6210\" / \"updated\"\n const hasContradictionSignal =\n /\u6539\u6210|\u53D8\u6210|\u66F4\u65B0\u4E3A|\u6362\u6210|\u4E0D\u518D|\u53D6\u6D88\u4E86|changed to|updated to|no longer|switched to/i.test(newText) ||\n (oldText.match(/\\d+/) && newText.match(/\\d+/) && cosineSim > 0.80);\n\n if (hasContradictionSignal) {\n // Audit: record contradiction-based expiration (version history)\n _auditExpire?.(match.entry.id, match.entry.scope || \"global\", \"contradiction\",\n `old: \"${match.entry.text?.slice(0, 100)}\" \u2192 new: \"${newText.slice(0, 100)}\"`);\n\n // Demote old entry\n const existingMeta = parseSmartMetadata(match.entry.metadata, match.entry);\n const oldImportance = match.entry.importance ?? 0.7;\n existingMeta.expired_at = new Date().toISOString();\n existingMeta.expired_reason = `superseded: ${newText.slice(0, 80)}`;\n await this.update(\n match.entry.id,\n {\n importance: Math.max(0.05, oldImportance * 0.1),\n metadata: stringifySmartMetadata(existingMeta),\n },\n );\n }\n }\n }\n } catch {\n // Conflict check failure \u2192 proceed with normal write\n }\n }\n\n // \u2500\u2500 Step 2: Normal write \u2500\u2500\n const fullEntry: MemoryEntry = {\n ...entry,\n id: randomUUID(),\n timestamp: Date.now(),\n metadata: entry.metadata || \"{}\",\n };\n\n try {\n if (this._adapter) {\n // TODO: type this \u2014 adapter.add signature doesn't match MemoryEntry exactly\n await this._adapter.add([fullEntry as any]);\n } else {\n await this.table!.add([fullEntry]);\n }\n } catch (err: unknown) {\n const e = err as NodeJS.ErrnoException;\n const code = e.code || \"\";\n const message = e.message || String(err);\n throw new Error(\n `Failed to store memory in \"${this.config.dbPath}\": ${code} ${message}`,\n );\n }\n\n // Audit: record creation\n _auditCreate?.(fullEntry.id, fullEntry.scope, fullEntry.scope, \"store\", fullEntry.text?.slice(0, 200));\n\n // \u2500\u2500 Step 3: Graphiti \u65F6\u5E8F\u56FE\u8C31\u53CC\u5199 with WAL \u2500\u2500\n const textLen = (fullEntry.text || \"\").length;\n const importance = typeof fullEntry.importance === \"number\" ? fullEntry.importance : 0.7;\n if (process.env.GRAPHITI_ENABLED === \"true\" && importance >= 0.5 && textLen >= 20) {\n const graphitiBase = process.env.GRAPHITI_BASE_URL || \"http://127.0.0.1:18799\";\n const scope = fullEntry.scope || \"default\";\n const groupId = scope.startsWith(\"agent:\") ? scope.split(\":\")[1] || \"default\" : \"default\";\n const walTs = new Date(fullEntry.timestamp).toISOString();\n\n // Write WAL pending entry before Graphiti call (Pro feature)\n if (walAppend) {\n walAppend({\n ts: walTs,\n action: \"write\",\n text: fullEntry.text,\n scope,\n category: fullEntry.category || \"fact\",\n groupId,\n importance,\n status: \"pending\",\n }).catch(() => {});\n }\n\n // Async Graphiti write (WAL tracking is Pro, Graphiti write is Core)\n fetch(`${graphitiBase}/episodes`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n text: `[${fullEntry.category || \"fact\"}] ${fullEntry.text}`,\n group_id: groupId,\n reference_time: walTs,\n source: `lancedb-pro-store-${groupId}`,\n category: fullEntry.category || \"fact\",\n }),\n signal: AbortSignal.timeout(15000),\n })\n .then(() => {\n walMarkCommitted?.(walTs).catch(() => {});\n })\n .catch((err) => {\n walMarkFailed?.(walTs, String(err)).catch(() => {});\n });\n }\n\n return fullEntry;\n }\n\n /**\n * Import a pre-built entry while preserving its id/timestamp.\n * Used for re-embedding / migration / A/B testing across embedding models.\n * Intentionally separate from `store()` to keep normal writes simple.\n */\n async importEntry(entry: MemoryEntry): Promise<MemoryEntry> {\n await this.ensureInitialized();\n\n if (!entry.id || typeof entry.id !== \"string\") {\n throw new Error(\"importEntry requires a stable id\");\n }\n\n const vector = entry.vector || [];\n if (!Array.isArray(vector) || vector.length !== this.config.vectorDim) {\n throw new Error(\n `Vector dimension mismatch: expected ${this.config.vectorDim}, got ${Array.isArray(vector) ? vector.length : \"non-array\"}`,\n );\n }\n\n const full: MemoryEntry = {\n ...entry,\n scope: entry.scope || \"global\",\n importance: Number.isFinite(entry.importance) ? entry.importance : 0.7,\n timestamp: Number.isFinite(entry.timestamp)\n ? entry.timestamp\n : Date.now(),\n metadata: entry.metadata || \"{}\",\n };\n\n await this.table!.add([full]);\n return full;\n }\n\n async hasId(id: string): Promise<boolean> {\n await this.ensureInitialized();\n if (this._adapter) {\n const results = await this._adapter.query({ where: `id = '${escapeSqlLiteral(id)}'`, limit: 1 });\n return results.length > 0;\n }\n const safeId = escapeSqlLiteral(id);\n const res = await this.table!.query()\n .select([\"id\"])\n .where(`id = '${safeId}'`)\n .limit(1)\n .toArray();\n return res.length > 0;\n }\n\n async getById(id: string, scopeFilter?: string[]): Promise<MemoryEntry | null> {\n await this.ensureInitialized();\n\n if (this._adapter) {\n const results = await this._adapter.query({ where: `id = '${escapeSqlLiteral(id)}'`, limit: 1 });\n if (results.length === 0) return null;\n const r = results[0];\n return { id: r.id, text: r.text, vector: r.vector, category: r.category as MemoryEntry[\"category\"], scope: r.scope, importance: r.importance, timestamp: r.timestamp, metadata: r.metadata } as MemoryEntry;\n }\n\n const safeId = escapeSqlLiteral(id);\n const rows = await this.table!\n .query()\n .where(`id = '${safeId}'`)\n .limit(1)\n .toArray();\n\n if (rows.length === 0) return null;\n\n const row = rows[0];\n const rowScope = (row.scope as string | undefined) ?? \"global\";\n if (scopeFilter && scopeFilter.length > 0 && !scopeFilter.includes(rowScope)) {\n return null;\n }\n\n return {\n id: row.id as string,\n text: row.text as string,\n vector: Array.from(row.vector as Iterable<number>),\n category: row.category as MemoryEntry[\"category\"],\n scope: rowScope,\n importance: Number(row.importance),\n timestamp: Number(row.timestamp),\n metadata: (row.metadata as string) || \"{}\",\n };\n }\n\n async vectorSearch(vector: number[], limit = 5, minScore = 0.3, scopeFilter?: string[]): Promise<MemorySearchResult[]> {\n await this.ensureInitialized();\n\n // Adapter path: delegate to backend\n if (this._adapter) {\n const results = await this._adapter.vectorSearch(vector, limit, minScore, scopeFilter);\n return results.map(r => ({\n entry: { id: r.record.id, text: r.record.text, vector: r.record.vector, category: r.record.category as MemoryEntry[\"category\"], scope: r.record.scope, importance: r.record.importance, timestamp: r.record.timestamp, metadata: r.record.metadata } as MemoryEntry,\n score: r.score,\n }));\n }\n\n const safeLimit = clampInt(limit, 1, 20);\n const fetchLimit = Math.min(safeLimit * 10, 200); // Over-fetch for scope filtering\n\n let query = this.table!.vectorSearch(vector).distanceType('cosine').limit(fetchLimit);\n\n // Apply scope filter if provided\n if (scopeFilter && scopeFilter.length > 0) {\n const scopeConditions = scopeFilter\n .map((scope) => `scope = '${escapeSqlLiteral(scope)}'`)\n .join(\" OR \");\n query = query.where(`(${scopeConditions}) OR scope IS NULL`); // NULL for backward compatibility\n }\n\n const results = await query.toArray();\n const mapped: MemorySearchResult[] = [];\n\n for (const row of results) {\n const distance = Number(row._distance ?? 0);\n const score = 1 / (1 + distance);\n\n if (score < minScore) continue;\n\n const rowScope = (row.scope as string | undefined) ?? \"global\";\n\n // Double-check scope filter in application layer\n if (\n scopeFilter &&\n scopeFilter.length > 0 &&\n !scopeFilter.includes(rowScope)\n ) {\n continue;\n }\n\n mapped.push({\n entry: {\n id: row.id as string,\n text: row.text as string,\n vector: row.vector as number[],\n category: row.category as MemoryEntry[\"category\"],\n scope: rowScope,\n importance: Number(row.importance),\n timestamp: Number(row.timestamp),\n metadata: (row.metadata as string) || \"{}\",\n },\n score,\n });\n\n if (mapped.length >= safeLimit) break;\n }\n\n return mapped;\n }\n\n async bm25Search(\n query: string,\n limit = 5,\n scopeFilter?: string[],\n ): Promise<MemorySearchResult[]> {\n await this.ensureInitialized();\n\n // Adapter path\n if (this._adapter) {\n const results = await this._adapter.fullTextSearch(query, limit, scopeFilter);\n return results.map(r => ({\n entry: { id: r.record.id, text: r.record.text, vector: r.record.vector, category: r.record.category as MemoryEntry[\"category\"], scope: r.record.scope, importance: r.record.importance, timestamp: r.record.timestamp, metadata: r.record.metadata } as MemoryEntry,\n score: r.score,\n }));\n }\n\n const safeLimit = clampInt(limit, 1, 20);\n\n if (!this.ftsIndexCreated) {\n return this.lexicalFallbackSearch(query, safeLimit, scopeFilter);\n }\n\n try {\n // Use FTS query type explicitly\n let searchQuery = this.table!.search(query, \"fts\").limit(safeLimit);\n\n // Apply scope filter if provided\n if (scopeFilter && scopeFilter.length > 0) {\n const scopeConditions = scopeFilter\n .map((scope) => `scope = '${escapeSqlLiteral(scope)}'`)\n .join(\" OR \");\n searchQuery = searchQuery.where(\n `(${scopeConditions}) OR scope IS NULL`,\n );\n }\n\n const results = await searchQuery.toArray();\n const mapped: MemorySearchResult[] = [];\n\n for (const row of results) {\n const rowScope = (row.scope as string | undefined) ?? \"global\";\n\n // Double-check scope filter in application layer\n if (\n scopeFilter &&\n scopeFilter.length > 0 &&\n !scopeFilter.includes(rowScope)\n ) {\n continue;\n }\n\n // LanceDB FTS _score is raw BM25 (unbounded). Normalize with sigmoid.\n // LanceDB may return BigInt for numeric columns; coerce safely.\n const rawScore = row._score != null ? Number(row._score) : 0;\n const normalizedScore =\n rawScore > 0 ? 1 / (1 + Math.exp(-rawScore / 5)) : 0.5;\n\n mapped.push({\n entry: {\n id: row.id as string,\n text: row.text as string,\n vector: row.vector as number[],\n category: row.category as MemoryEntry[\"category\"],\n scope: rowScope,\n importance: Number(row.importance),\n timestamp: Number(row.timestamp),\n metadata: (row.metadata as string) || \"{}\",\n },\n score: normalizedScore,\n });\n }\n\n if (mapped.length > 0) {\n return mapped;\n }\n return this.lexicalFallbackSearch(query, safeLimit, scopeFilter);\n } catch (err) {\n log.warn(\"BM25 search failed, falling back to empty results:\", err);\n return this.lexicalFallbackSearch(query, safeLimit, scopeFilter);\n }\n }\n\n private async lexicalFallbackSearch(query: string, limit: number, scopeFilter?: string[]): Promise<MemorySearchResult[]> {\n const trimmedQuery = query.trim();\n if (!trimmedQuery) return [];\n\n let searchQuery = this.table!.query().select([\n \"id\",\n \"text\",\n \"vector\",\n \"category\",\n \"scope\",\n \"importance\",\n \"timestamp\",\n \"metadata\",\n ]);\n\n if (scopeFilter && scopeFilter.length > 0) {\n const scopeConditions = scopeFilter\n .map(scope => `scope = '${escapeSqlLiteral(scope)}'`)\n .join(\" OR \");\n searchQuery = searchQuery.where(`(${scopeConditions}) OR scope IS NULL`);\n }\n\n const rows = await searchQuery.toArray();\n const matches: MemorySearchResult[] = [];\n\n for (const row of rows) {\n const rowScope = (row.scope as string | undefined) ?? \"global\";\n if (scopeFilter && scopeFilter.length > 0 && !scopeFilter.includes(rowScope)) {\n continue;\n }\n\n const entry: MemoryEntry = {\n id: row.id as string,\n text: row.text as string,\n vector: row.vector as number[],\n category: row.category as MemoryEntry[\"category\"],\n scope: rowScope,\n importance: Number(row.importance),\n timestamp: Number(row.timestamp),\n metadata: (row.metadata as string) || \"{}\",\n };\n\n const metadata = parseSmartMetadata(entry.metadata, entry);\n const score = scoreLexicalHit(trimmedQuery, [\n { text: entry.text, weight: 1 },\n { text: metadata.l0_abstract, weight: 0.98 },\n { text: metadata.l1_overview, weight: 0.92 },\n { text: metadata.l2_content, weight: 0.96 },\n ]);\n\n if (score <= 0) continue;\n matches.push({ entry, score });\n }\n\n return matches\n .sort((a, b) => b.score - a.score || b.entry.timestamp - a.entry.timestamp)\n .slice(0, limit);\n }\n\n async delete(id: string, scopeFilter?: string[]): Promise<boolean> {\n await this.ensureInitialized();\n\n // Support both full UUID and short prefix (8+ hex chars)\n const uuidRegex =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n const prefixRegex = /^[0-9a-f]{8,}$/i;\n const isFullId = uuidRegex.test(id);\n const isPrefix = !isFullId && prefixRegex.test(id);\n\n if (!isFullId && !isPrefix) {\n throw new Error(`Invalid memory ID format: ${id}`);\n }\n\n let candidates: Record<string, unknown>[];\n if (isFullId) {\n candidates = await this.table!.query()\n .where(`id = '${id}'`)\n .limit(1)\n .toArray();\n } else {\n // Prefix match: fetch candidates and filter in app layer\n const all = await this.table!.query()\n .select([\"id\", \"scope\"])\n .limit(1000)\n .toArray();\n candidates = all.filter((r: Record<string, unknown>) => (r.id as string).startsWith(id));\n if (candidates.length > 1) {\n throw new Error(\n `Ambiguous prefix \"${id}\" matches ${candidates.length} memories. Use a longer prefix or full ID.`,\n );\n }\n }\n if (candidates.length === 0) {\n return false;\n }\n\n const resolvedId = candidates[0].id as string;\n const rowScope = (candidates[0].scope as string | undefined) ?? \"global\";\n\n // Check scope permissions\n if (\n scopeFilter &&\n scopeFilter.length > 0 &&\n !scopeFilter.includes(rowScope)\n ) {\n throw new Error(`Memory ${resolvedId} is outside accessible scopes`);\n }\n\n // Audit: record deletion with old value for version history\n _auditDelete?.([resolvedId], rowScope, \"user-request\");\n\n if (this._adapter) {\n await this._adapter.delete(`id = '${escapeSqlLiteral(resolvedId)}'`);\n } else {\n await this.table!.delete(`id = '${resolvedId}'`);\n }\n return true;\n }\n\n async list(\n scopeFilter?: string[],\n category?: string,\n limit = 20,\n offset = 0,\n ): Promise<MemoryEntry[]> {\n await this.ensureInitialized();\n\n let query = this.table!.query();\n\n // Build where conditions\n const conditions: string[] = [];\n\n if (scopeFilter && scopeFilter.length > 0) {\n const scopeConditions = scopeFilter\n .map((scope) => `scope = '${escapeSqlLiteral(scope)}'`)\n .join(\" OR \");\n conditions.push(`((${scopeConditions}) OR scope IS NULL)`);\n }\n\n if (category) {\n conditions.push(`category = '${escapeSqlLiteral(category)}'`);\n }\n\n if (conditions.length > 0) {\n query = query.where(conditions.join(\" AND \"));\n }\n\n // Fetch all matching rows (no pre-limit) so app-layer sort is correct across full dataset\n const results = await query\n .select([\n \"id\",\n \"text\",\n \"category\",\n \"scope\",\n \"importance\",\n \"timestamp\",\n \"metadata\",\n ])\n .toArray();\n\n return results\n .map(\n (row): MemoryEntry => ({\n id: row.id as string,\n text: row.text as string,\n vector: [], // Don't include vectors in list results for performance\n category: row.category as MemoryEntry[\"category\"],\n scope: (row.scope as string | undefined) ?? \"global\",\n importance: Number(row.importance),\n timestamp: Number(row.timestamp),\n metadata: (row.metadata as string) || \"{}\",\n }),\n )\n .sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0))\n .slice(offset, offset + limit);\n }\n\n async stats(scopeFilter?: string[]): Promise<{\n totalCount: number;\n scopeCounts: Record<string, number>;\n categoryCounts: Record<string, number>;\n }> {\n await this.ensureInitialized();\n\n let query = this.table!.query();\n\n if (scopeFilter && scopeFilter.length > 0) {\n const scopeConditions = scopeFilter\n .map((scope) => `scope = '${escapeSqlLiteral(scope)}'`)\n .join(\" OR \");\n query = query.where(`((${scopeConditions}) OR scope IS NULL)`);\n }\n\n const results = await query.select([\"scope\", \"category\"]).toArray();\n\n const scopeCounts: Record<string, number> = {};\n const categoryCounts: Record<string, number> = {};\n\n for (const row of results) {\n const scope = (row.scope as string | undefined) ?? \"global\";\n const category = row.category as string;\n\n scopeCounts[scope] = (scopeCounts[scope] || 0) + 1;\n categoryCounts[category] = (categoryCounts[category] || 0) + 1;\n }\n\n return {\n totalCount: results.length,\n scopeCounts,\n categoryCounts,\n };\n }\n\n async update(\n id: string,\n updates: {\n text?: string;\n vector?: number[];\n importance?: number;\n category?: MemoryEntry[\"category\"];\n metadata?: string;\n },\n scopeFilter?: string[],\n ): Promise<MemoryEntry | null> {\n await this.ensureInitialized();\n\n return this.runSerializedUpdate(async () => {\n // Support both full UUID and short prefix (8+ hex chars), same as delete()\n const uuidRegex =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n const prefixRegex = /^[0-9a-f]{8,}$/i;\n const isFullId = uuidRegex.test(id);\n const isPrefix = !isFullId && prefixRegex.test(id);\n\n if (!isFullId && !isPrefix) {\n throw new Error(`Invalid memory ID format: ${id}`);\n }\n\n let rows: Record<string, unknown>[];\n if (isFullId) {\n const safeId = escapeSqlLiteral(id);\n rows = await this.table!.query()\n .where(`id = '${safeId}'`)\n .limit(1)\n .toArray();\n } else {\n // Prefix match\n const all = await this.table!.query()\n .select([\n \"id\",\n \"text\",\n \"vector\",\n \"category\",\n \"scope\",\n \"importance\",\n \"timestamp\",\n \"metadata\",\n ])\n .limit(1000)\n .toArray();\n rows = all.filter((r: Record<string, unknown>) => (r.id as string).startsWith(id));\n if (rows.length > 1) {\n throw new Error(\n `Ambiguous prefix \"${id}\" matches ${rows.length} memories. Use a longer prefix or full ID.`,\n );\n }\n }\n\n if (rows.length === 0) return null;\n\n const row = rows[0];\n const rowScope = (row.scope as string | undefined) ?? \"global\";\n\n // Check scope permissions\n if (\n scopeFilter &&\n scopeFilter.length > 0 &&\n !scopeFilter.includes(rowScope)\n ) {\n throw new Error(`Memory ${id} is outside accessible scopes`);\n }\n\n const original: MemoryEntry = {\n id: row.id as string,\n text: row.text as string,\n vector: Array.from(row.vector as Iterable<number>),\n category: row.category as MemoryEntry[\"category\"],\n scope: rowScope,\n importance: Number(row.importance),\n timestamp: Number(row.timestamp),\n metadata: (row.metadata as string) || \"{}\",\n };\n\n // Build updated entry, preserving original timestamp\n const updated: MemoryEntry = {\n ...original,\n text: updates.text ?? original.text,\n vector: updates.vector ?? original.vector,\n category: updates.category ?? original.category,\n scope: rowScope,\n importance: updates.importance ?? original.importance,\n timestamp: original.timestamp, // preserve original\n metadata: updates.metadata ?? original.metadata,\n };\n\n // Audit: record update with old value snapshot (version history)\n _auditUpdate?.(original.id, rowScope, \"memory-update\",\n JSON.stringify({\n old: { text: original.text?.slice(0, 200), importance: original.importance, category: original.category },\n new: { text: updated.text?.slice(0, 200), importance: updated.importance, category: updated.category },\n })\n );\n\n // LanceDB doesn't support in-place update; delete + re-add.\n // Serialize updates per store instance to avoid stale rollback races.\n // If the add fails after delete, attempt best-effort recovery without\n // overwriting a newer concurrent successful update.\n const rollbackCandidate =\n (await this.getById(original.id).catch(() => null)) ?? original;\n const resolvedId = escapeSqlLiteral(row.id as string);\n await this.table!.delete(`id = '${resolvedId}'`);\n try {\n await this.table!.add([updated]);\n } catch (addError) {\n const current = await this.getById(original.id).catch(() => null);\n if (current) {\n throw new Error(\n `Failed to update memory ${id}: write failed after delete, but an existing record was preserved. ` +\n `Write error: ${addError instanceof Error ? addError.message : String(addError)}`,\n );\n }\n\n try {\n await this.table!.add([rollbackCandidate]);\n } catch (rollbackError) {\n throw new Error(\n `Failed to update memory ${id}: write failed after delete, and rollback also failed. ` +\n `Write error: ${addError instanceof Error ? addError.message : String(addError)}. ` +\n `Rollback error: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}`,\n );\n }\n\n throw new Error(\n `Failed to update memory ${id}: write failed after delete, latest available record restored. ` +\n `Write error: ${addError instanceof Error ? addError.message : String(addError)}`,\n );\n }\n\n return updated;\n });\n }\n\n private async runSerializedUpdate<T>(action: () => Promise<T>): Promise<T> {\n const previous = this.updateQueue;\n let release: (() => void) | undefined;\n const lock = new Promise<void>((resolve) => {\n release = resolve;\n });\n this.updateQueue = previous.then(() => lock);\n\n await previous;\n try {\n return await action();\n } finally {\n release?.();\n }\n }\n\n async patchMetadata(\n id: string,\n patch: MetadataPatch,\n scopeFilter?: string[],\n ): Promise<MemoryEntry | null> {\n const existing = await this.getById(id, scopeFilter);\n if (!existing) return null;\n\n const metadata = buildSmartMetadata(existing, patch);\n return this.update(\n id,\n { metadata: stringifySmartMetadata(metadata) },\n scopeFilter,\n );\n }\n\n async bulkDelete(scopeFilter: string[], beforeTimestamp?: number): Promise<number> {\n await this.ensureInitialized();\n\n const conditions: string[] = [];\n\n if (scopeFilter.length > 0) {\n const scopeConditions = scopeFilter\n .map((scope) => `scope = '${escapeSqlLiteral(scope)}'`)\n .join(\" OR \");\n conditions.push(`(${scopeConditions})`);\n }\n\n if (beforeTimestamp) {\n conditions.push(`timestamp < ${beforeTimestamp}`);\n }\n\n if (conditions.length === 0) {\n throw new Error(\n \"Bulk delete requires at least scope or timestamp filter for safety\",\n );\n }\n\n const whereClause = conditions.join(\" AND \");\n\n // Count first\n const countResults = await this.table!.query().where(whereClause).toArray();\n const deleteCount = countResults.length;\n\n // Then delete\n if (deleteCount > 0) {\n await this.table!.delete(whereClause);\n }\n\n return deleteCount;\n }\n\n /** Last FTS error for diagnostics */\n private _lastFtsError: string | null = null;\n\n get lastFtsError(): string | null {\n return this._lastFtsError;\n }\n\n /** Get FTS index health status */\n getFtsStatus(): { available: boolean; lastError: string | null } {\n return {\n available: this.ftsIndexCreated,\n lastError: this._lastFtsError,\n };\n }\n\n /** Rebuild FTS index (drops and recreates). Useful for recovery after corruption. */\n async rebuildFtsIndex(): Promise<{ success: boolean; error?: string }> {\n await this.ensureInitialized();\n try {\n // Drop existing FTS index if any\n const indices = await this.table!.listIndices();\n for (const idx of indices) {\n if (idx.indexType === \"FTS\" || idx.columns?.includes(\"text\")) {\n try {\n // TODO: type this \u2014 LanceDB index type lacks .name property in typings\n await this.table!.dropIndex((idx as any).name || \"text\");\n } catch (err) {\n // TODO: type this \u2014 LanceDB index type lacks .name property in typings\n log.warn(`dropIndex(${(idx as any).name || \"text\"}) failed:`, err);\n }\n }\n }\n // Recreate\n await this.createFtsIndex(this.table!);\n this.ftsIndexCreated = true;\n this._lastFtsError = null;\n return { success: true };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n this._lastFtsError = msg;\n this.ftsIndexCreated = false;\n return { success: false, error: msg };\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["sample", "results"]
|
|
7
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tier-manager.d.ts","sourceRoot":"","sources":["../../src/tier-manager.ts"],"names":[],"mappings":"AACA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAMpD,MAAM,WAAW,UAAU;IACzB,4DAA4D;IAC5D,mBAAmB,EAAE,MAAM,CAAC;IAC5B,sEAAsE;IACtE,sBAAsB,EAAE,MAAM,CAAC;IAC/B,2DAA2D;IAC3D,uBAAuB,EAAE,MAAM,CAAC;IAChC,8EAA8E;IAC9E,4BAA4B,EAAE,MAAM,CAAC;IACrC,qFAAqF;IACrF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,sBAAsB,EAAE,MAAM,CAAC;IAC/B,6EAA6E;IAC7E,yBAAyB,EAAE,MAAM,CAAC;CACnC;AAED,eAAO,MAAM,mBAAmB,EAAE,UAQjC,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,UAAU,CAAC;IACrB,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,QAAQ,CACN,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,UAAU,EACtB,GAAG,CAAC,EAAE,MAAM,GACX,cAAc,GAAG,IAAI,CAAC;IAEzB;;OAEG;IACH,WAAW,CACT,QAAQ,EAAE,cAAc,EAAE,EAC1B,WAAW,EAAE,UAAU,EAAE,EACzB,GAAG,CAAC,EAAE,MAAM,GACX,cAAc,EAAE,CAAC;CACrB;AAQD,wBAAgB,iBAAiB,CAC/B,MAAM,GAAE,UAAgC,GACvC,WAAW,CAgGb"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/tier-manager.ts"],
|
|
4
|
-
"sourcesContent": ["// SPDX-License-Identifier: MIT\n/**\n * Tier Manager \u2014 Three-tier memory promotion/demotion system\n *\n * Tiers:\n * - Core (decay floor 0.9): Identity-level facts, almost never forgotten\n * - Working (decay floor 0.7): Active context, ages out without reinforcement\n * - Peripheral (decay floor 0.5): Low-priority or aging memories\n *\n * Promotion: Peripheral \u2192 Working \u2192 Core (based on access, composite score, importance)\n * Demotion: Core \u2192 Working \u2192 Peripheral (based on decay, age)\n */\n\nimport type { MemoryTier } from \"./memory-categories.js\";\nimport type { DecayScore } from \"./decay-engine.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface TierConfig {\n /** Minimum access count for Core promotion (default: 10) */\n coreAccessThreshold: number;\n /** Minimum composite decay score for Core promotion (default: 0.7) */\n coreCompositeThreshold: number;\n /** Minimum importance for Core promotion (default: 0.8) */\n coreImportanceThreshold: number;\n /** Composite threshold below which to demote to Peripheral (default: 0.15) */\n peripheralCompositeThreshold: number;\n /** Age in days after which infrequent memories demote to Peripheral (default: 60) */\n peripheralAgeDays: number;\n /** Minimum access count for Working promotion from Peripheral (default: 3) */\n workingAccessThreshold: number;\n /** Minimum composite for Working promotion from Peripheral (default: 0.4) */\n workingCompositeThreshold: number;\n}\n\nexport const DEFAULT_TIER_CONFIG: TierConfig = {\n coreAccessThreshold: 10,\n coreCompositeThreshold: 0.7,\n coreImportanceThreshold: 0.8,\n peripheralCompositeThreshold: 0.15,\n peripheralAgeDays: 60,\n workingAccessThreshold: 3,\n workingCompositeThreshold: 0.4,\n};\n\nexport interface TierTransition {\n memoryId: string;\n fromTier: MemoryTier;\n toTier: MemoryTier;\n reason: string;\n}\n\n/** Minimal memory fields needed for tier evaluation. */\nexport interface TierableMemory {\n id: string;\n tier: MemoryTier;\n importance: number;\n accessCount: number;\n createdAt: number;\n}\n\nexport interface TierManager {\n /**\n * Evaluate whether a memory should change tiers.\n * Returns the transition if a change is needed, null otherwise.\n */\n evaluate(\n memory: TierableMemory,\n decayScore: DecayScore,\n now?: number,\n ): TierTransition | null;\n\n /**\n * Evaluate multiple memories and return all transitions.\n */\n evaluateAll(\n memories: TierableMemory[],\n decayScores: DecayScore[],\n now?: number,\n ): TierTransition[];\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nconst MS_PER_DAY = 86_400_000;\n\nexport function createTierManager(\n config: TierConfig = DEFAULT_TIER_CONFIG,\n): TierManager {\n function evaluate(\n memory: TierableMemory,\n decayScore: DecayScore,\n now: number = Date.now(),\n ): TierTransition | null {\n const ageDays = (now - memory.createdAt) / MS_PER_DAY;\n\n switch (memory.tier) {\n case \"peripheral\": {\n // Promote to Working?\n if (\n memory.accessCount >= config.workingAccessThreshold &&\n decayScore.composite >= config.workingCompositeThreshold\n ) {\n return {\n memoryId: memory.id,\n fromTier: \"peripheral\",\n toTier: \"working\",\n reason: `Access count (${memory.accessCount}) >= ${config.workingAccessThreshold} and composite (${decayScore.composite.toFixed(2)}) >= ${config.workingCompositeThreshold}`,\n };\n }\n break;\n }\n\n case \"working\": {\n // Promote to Core?\n if (\n memory.accessCount >= config.coreAccessThreshold &&\n decayScore.composite >= config.coreCompositeThreshold &&\n memory.importance >= config.coreImportanceThreshold\n ) {\n return {\n memoryId: memory.id,\n fromTier: \"working\",\n toTier: \"core\",\n reason: `High access (${memory.accessCount}), composite (${decayScore.composite.toFixed(2)}), importance (${memory.importance})`,\n };\n }\n\n // Demote to Peripheral?\n if (\n decayScore.composite < config.peripheralCompositeThreshold ||\n (ageDays > config.peripheralAgeDays &&\n memory.accessCount < config.workingAccessThreshold)\n ) {\n return {\n memoryId: memory.id,\n fromTier: \"working\",\n toTier: \"peripheral\",\n reason: `Low composite (${decayScore.composite.toFixed(2)}) or aged ${ageDays.toFixed(0)} days with low access (${memory.accessCount})`,\n };\n }\n break;\n }\n\n case \"core\": {\n // Demote to Working? (Core rarely demotes, but it can)\n if (\n decayScore.composite < config.peripheralCompositeThreshold &&\n memory.accessCount < config.workingAccessThreshold\n ) {\n return {\n memoryId: memory.id,\n fromTier: \"core\",\n toTier: \"working\",\n reason: `Severely low composite (${decayScore.composite.toFixed(2)}) and access (${memory.accessCount})`,\n };\n }\n break;\n }\n }\n\n return null;\n }\n\n return {\n evaluate,\n\n evaluateAll(memories, decayScores, now = Date.now()) {\n const scoreMap = new Map(decayScores.map((s) => [s.memoryId, s]));\n const transitions: TierTransition[] = [];\n\n for (const memory of memories) {\n const score = scoreMap.get(memory.id);\n if (!score) continue;\n\n const transition = evaluate(memory, score, now);\n if (transition) {\n transitions.push(transition);\n }\n }\n\n return transitions;\n },\n };\n}\n"],
|
|
5
|
-
"mappings": "AAqCO,MAAM,sBAAkC;AAAA,EAC7C,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,yBAAyB;AAAA,EACzB,8BAA8B;AAAA,EAC9B,mBAAmB;AAAA,EACnB,wBAAwB;AAAA,EACxB,2BAA2B;AAC7B;AA2CA,MAAM,aAAa;AAEZ,SAAS,kBACd,SAAqB,qBACR;AACb,WAAS,SACP,QACA,YACA,MAAc,KAAK,IAAI,GACA;AACvB,UAAM,WAAW,MAAM,OAAO,aAAa;AAE3C,YAAQ,OAAO,MAAM;AAAA,MACnB,KAAK,cAAc;AAEjB,YACE,OAAO,eAAe,OAAO,0BAC7B,WAAW,aAAa,OAAO,2BAC/B;AACA,iBAAO;AAAA,YACL,UAAU,OAAO;AAAA,YACjB,UAAU;AAAA,YACV,QAAQ;AAAA,YACR,QAAQ,iBAAiB,OAAO,WAAW,QAAQ,OAAO,sBAAsB,mBAAmB,WAAW,UAAU,QAAQ,CAAC,CAAC,QAAQ,OAAO,yBAAyB;AAAA,UAC5K;AAAA,QACF;AACA;AAAA,MACF;AAAA,MAEA,KAAK,WAAW;AAEd,YACE,OAAO,eAAe,OAAO,uBAC7B,WAAW,aAAa,OAAO,0BAC/B,OAAO,cAAc,OAAO,yBAC5B;AACA,iBAAO;AAAA,YACL,UAAU,OAAO;AAAA,YACjB,UAAU;AAAA,YACV,QAAQ;AAAA,YACR,QAAQ,gBAAgB,OAAO,WAAW,iBAAiB,WAAW,UAAU,QAAQ,CAAC,CAAC,kBAAkB,OAAO,UAAU;AAAA,UAC/H;AAAA,QACF;AAGA,YACE,WAAW,YAAY,OAAO,gCAC7B,UAAU,OAAO,qBAChB,OAAO,cAAc,OAAO,wBAC9B;AACA,iBAAO;AAAA,YACL,UAAU,OAAO;AAAA,YACjB,UAAU;AAAA,YACV,QAAQ;AAAA,YACR,QAAQ,kBAAkB,WAAW,UAAU,QAAQ,CAAC,CAAC,aAAa,QAAQ,QAAQ,CAAC,CAAC,0BAA0B,OAAO,WAAW;AAAA,UACtI;AAAA,QACF;AACA;AAAA,MACF;AAAA,MAEA,KAAK,QAAQ;AAEX,YACE,WAAW,YAAY,OAAO,gCAC9B,OAAO,cAAc,OAAO,wBAC5B;AACA,iBAAO;AAAA,YACL,UAAU,OAAO;AAAA,YACjB,UAAU;AAAA,YACV,QAAQ;AAAA,YACR,QAAQ,2BAA2B,WAAW,UAAU,QAAQ,CAAC,CAAC,iBAAiB,OAAO,WAAW;AAAA,UACvG;AAAA,QACF;AACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IAEA,YAAY,UAAU,aAAa,MAAM,KAAK,IAAI,GAAG;AACnD,YAAM,WAAW,IAAI,IAAI,YAAY,IAAI,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;AAChE,YAAM,cAAgC,CAAC;AAEvC,iBAAW,UAAU,UAAU;AAC7B,cAAM,QAAQ,SAAS,IAAI,OAAO,EAAE;AACpC,YAAI,CAAC,MAAO;AAEZ,cAAM,aAAa,SAAS,QAAQ,OAAO,GAAG;AAC9C,YAAI,YAAY;AACd,sBAAY,KAAK,UAAU;AAAA,QAC7B;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
package/dist/src/tools.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/tools.ts"],"names":[],"mappings":"AACA;;;GAGG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAI7D,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,gBAAgB,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAc9C,eAAO,MAAM,iBAAiB,8EAOpB,CAAC;AAQX,MAAM,MAAM,cAAc,GAAG,CAC3B,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5E,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,KACzC,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,UAAU,WAAW;IACnB,SAAS,EAAE,eAAe,CAAC;IAC3B,KAAK,EAAE,WAAW,CAAC;IACnB,YAAY,EAAE,kBAAkB,CAAC;IACjC,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;CAClC;AA+FD,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,iBAAiB,EAAE,OAAO,EAAE,WAAW,QA8D1F;AAED,wBAAgB,uCAAuC,CAAC,GAAG,EAAE,iBAAiB,EAAE,OAAO,EAAE,WAAW,QAqHnG;AAED,wBAAgB,iCAAiC,CAAC,GAAG,EAAE,iBAAiB,EAAE,OAAO,EAAE,WAAW,QAkD7F;AAMD,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE,WAAW,QAiIrB;AAED,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE,WAAW,QAoKrB;AAED,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE,WAAW,QAwJrB;AAMD,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE,WAAW,QAyKrB;AAMD,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE,WAAW,QAyFrB;AAED,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE,WAAW,QAwIrB;AAMD,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE;IACP,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACjC,QAoBP"}
|
package/dist/src/tools.js.map
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/tools.ts"],
|
|
4
|
-
"sourcesContent": ["// SPDX-License-Identifier: LicenseRef-Mnemo-Pro\n/**\n * Agent Tool Definitions\n * Memory management tools for AI agents\n */\n\nimport { Type } from \"@sinclair/typebox\";\nimport type { OpenClawPluginApi } from \"openclaw/plugin-sdk\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { MemoryRetriever, RetrievalResult } from \"./retriever.js\";\nimport type { MemoryStore } from \"./store.js\";\nimport { isNoise } from \"./noise-filter.js\";\nimport type { MemoryScopeManager } from \"./scopes.js\";\nimport type { Embedder } from \"./embedder.js\";\nimport {\n buildSmartMetadata,\n parseSmartMetadata,\n stringifySmartMetadata,\n} from \"./smart-metadata.js\";\nimport { appendSelfImprovementEntry, ensureSelfImprovementLearningFiles } from \"./self-improvement-files.js\";\nimport { getDisplayCategoryTag } from \"./reflection-metadata.js\";\nimport { log } from \"./logger.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport const MEMORY_CATEGORIES = [\n \"preference\",\n \"fact\",\n \"decision\",\n \"entity\",\n \"reflection\",\n \"other\",\n] as const;\n\nfunction stringEnum<T extends readonly [string, ...string[]]>(values: T) {\n return Type.Unsafe<T[number]>({\n type: \"string\",\n enum: [...values],\n });\n}\nexport type MdMirrorWriter = (\n entry: { text: string; category: string; scope: string; timestamp?: number },\n meta?: { source?: string; agentId?: string },\n) => Promise<void>;\n\ninterface ToolContext {\n retriever: MemoryRetriever;\n store: MemoryStore;\n scopeManager: MemoryScopeManager;\n embedder: Embedder;\n agentId?: string;\n workspaceDir?: string;\n mdMirror?: MdMirrorWriter | null;\n}\n\nfunction resolveAgentId(runtimeAgentId: unknown, fallback?: string): string | undefined {\n if (typeof runtimeAgentId === \"string\" && runtimeAgentId.trim().length > 0) return runtimeAgentId;\n if (typeof fallback === \"string\" && fallback.trim().length > 0) return fallback;\n return undefined;\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\nfunction clampInt(value: number, min: number, max: number): number {\n if (!Number.isFinite(value)) return min;\n return Math.min(max, Math.max(min, Math.floor(value)));\n}\n\nfunction clamp01(value: number, fallback = 0.7): number {\n if (!Number.isFinite(value)) return fallback;\n return Math.min(1, Math.max(0, value));\n}\n\nfunction sanitizeMemoryForSerialization(results: RetrievalResult[]) {\n return results.map((r) => ({\n id: r.entry.id,\n text: r.entry.text,\n category: getDisplayCategoryTag(r.entry),\n rawCategory: r.entry.category,\n scope: r.entry.scope,\n importance: r.entry.importance,\n score: r.score,\n sources: r.sources,\n }));\n}\n\nfunction parseAgentIdFromSessionKey(sessionKey: string | undefined): string | undefined {\n if (!sessionKey) return undefined;\n const m = /^agent:([^:]+):/.exec(sessionKey);\n return m?.[1];\n}\n\nfunction resolveRuntimeAgentId(\n staticAgentId: string | undefined,\n runtimeCtx: unknown,\n): string | undefined {\n if (!runtimeCtx || typeof runtimeCtx !== \"object\") return staticAgentId;\n const ctx = runtimeCtx as Record<string, unknown>;\n const ctxAgentId = typeof ctx.agentId === \"string\" ? ctx.agentId : undefined;\n const ctxSessionKey = typeof ctx.sessionKey === \"string\" ? ctx.sessionKey : undefined;\n return ctxAgentId || parseAgentIdFromSessionKey(ctxSessionKey) || staticAgentId;\n}\n\nfunction resolveToolContext(\n base: ToolContext,\n runtimeCtx: unknown,\n): ToolContext {\n return {\n ...base,\n agentId: resolveRuntimeAgentId(base.agentId, runtimeCtx),\n };\n}\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise(resolve => setTimeout(resolve, ms));\n}\n\nasync function retrieveWithRetry(\n retriever: MemoryRetriever,\n params: {\n query: string;\n limit: number;\n scopeFilter?: string[];\n category?: string;\n },\n): Promise<RetrievalResult[]> {\n let results = await retriever.retrieve(params);\n if (results.length === 0) {\n await sleep(75);\n results = await retriever.retrieve(params);\n }\n return results;\n}\n\nfunction resolveWorkspaceDir(toolCtx: unknown, fallback?: string): string {\n const runtime = toolCtx as Record<string, unknown> | undefined;\n const runtimePath = typeof runtime?.workspaceDir === \"string\" ? runtime.workspaceDir.trim() : \"\";\n if (runtimePath) return runtimePath;\n if (fallback && fallback.trim()) return fallback;\n return join(homedir(), \".openclaw\", \"workspace\");\n}\n\nfunction escapeRegExp(input: string): string {\n return input.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nexport function registerSelfImprovementLogTool(api: OpenClawPluginApi, context: ToolContext) {\n api.registerTool(\n (toolCtx) => ({\n name: \"self_improvement_log\",\n label: \"Self-Improvement Log\",\n description: \"Log structured learning/error entries into .learnings for governance and later distillation.\",\n parameters: Type.Object({\n type: stringEnum([\"learning\", \"error\"]),\n summary: Type.String({ description: \"One-line summary\" }),\n details: Type.Optional(Type.String({ description: \"Detailed context or error output\" })),\n suggestedAction: Type.Optional(Type.String({ description: \"Concrete action to prevent recurrence\" })),\n category: Type.Optional(Type.String({ description: \"learning category (correction/best_practice/knowledge_gap) when type=learning\" })),\n area: Type.Optional(Type.String({ description: \"frontend|backend|infra|tests|docs|config or custom area\" })),\n priority: Type.Optional(Type.String({ description: \"low|medium|high|critical\" })),\n }),\n async execute(_toolCallId, params) {\n const {\n type,\n summary,\n details = \"\",\n suggestedAction = \"\",\n category = \"best_practice\",\n area = \"config\",\n priority = \"medium\",\n } = params as {\n type: \"learning\" | \"error\";\n summary: string;\n details?: string;\n suggestedAction?: string;\n category?: string;\n area?: string;\n priority?: string;\n };\n try {\n const workspaceDir = resolveWorkspaceDir(toolCtx, context.workspaceDir);\n const { id: entryId, filePath } = await appendSelfImprovementEntry({\n baseDir: workspaceDir,\n type,\n summary,\n details,\n suggestedAction,\n category,\n area,\n priority,\n source: \"mnemo/self_improvement_log\",\n });\n const fileName = type === \"learning\" ? \"LEARNINGS.md\" : \"ERRORS.md\";\n\n return {\n content: [{ type: \"text\", text: `Logged ${type} entry ${entryId} to .learnings/${fileName}` }],\n details: { action: \"logged\", type, id: entryId, filePath },\n };\n } catch (error) {\n return {\n content: [{ type: \"text\", text: `Failed to log self-improvement entry: ${error instanceof Error ? error.message : String(error)}` }],\n details: { error: \"self_improvement_log_failed\", message: String(error) },\n };\n }\n },\n }),\n { name: \"self_improvement_log\" }\n );\n}\n\nexport function registerSelfImprovementExtractSkillTool(api: OpenClawPluginApi, context: ToolContext) {\n api.registerTool(\n (toolCtx) => ({\n name: \"self_improvement_extract_skill\",\n label: \"Extract Skill From Learning\",\n description: \"Create a new skill scaffold from a learning entry and mark the source learning as promoted_to_skill.\",\n parameters: Type.Object({\n learningId: Type.String({ description: \"Learning ID like LRN-YYYYMMDD-001\" }),\n skillName: Type.String({ description: \"Skill folder name, lowercase with hyphens\" }),\n sourceFile: Type.Optional(stringEnum([\"LEARNINGS.md\", \"ERRORS.md\"])),\n outputDir: Type.Optional(Type.String({ description: \"Relative output dir under workspace (default: skills)\" })),\n }),\n async execute(_toolCallId, params) {\n const { learningId, skillName, sourceFile = \"LEARNINGS.md\", outputDir = \"skills\" } = params as {\n learningId: string;\n skillName: string;\n sourceFile?: \"LEARNINGS.md\" | \"ERRORS.md\";\n outputDir?: string;\n };\n try {\n if (!/^(LRN|ERR)-\\d{8}-\\d{3}$/.test(learningId)) {\n return {\n content: [{ type: \"text\", text: \"Invalid learningId format. Use LRN-YYYYMMDD-001 / ERR-...\" }],\n details: { error: \"invalid_learning_id\" },\n };\n }\n if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(skillName)) {\n return {\n content: [{ type: \"text\", text: \"Invalid skillName. Use lowercase letters, numbers, and hyphens only.\" }],\n details: { error: \"invalid_skill_name\" },\n };\n }\n\n const workspaceDir = resolveWorkspaceDir(toolCtx, context.workspaceDir);\n await ensureSelfImprovementLearningFiles(workspaceDir);\n const learningsPath = join(workspaceDir, \".learnings\", sourceFile);\n const learningBody = await readFile(learningsPath, \"utf-8\");\n const escapedLearningId = escapeRegExp(learningId.trim());\n const entryRegex = new RegExp(`## \\\\[${escapedLearningId}\\\\][\\\\s\\\\S]*?(?=\\\\n## \\\\[|$)`, \"m\");\n const match = learningBody.match(entryRegex);\n if (!match) {\n return {\n content: [{ type: \"text\", text: `Learning entry ${learningId} not found in .learnings/${sourceFile}` }],\n details: { error: \"learning_not_found\", learningId, sourceFile },\n };\n }\n\n const summaryMatch = match[0].match(/### Summary\\n([\\s\\S]*?)\\n###/m);\n const summary = (summaryMatch?.[1] ?? \"Summarize the source learning here.\").trim();\n const safeOutputDir = outputDir\n .replace(/\\\\/g, \"/\")\n .split(\"/\")\n .filter((segment) => segment && segment !== \".\" && segment !== \"..\")\n .join(\"/\");\n const skillDir = join(workspaceDir, safeOutputDir || \"skills\", skillName);\n await mkdir(skillDir, { recursive: true });\n const skillPath = join(skillDir, \"SKILL.md\");\n const skillTitle = skillName\n .split(\"-\")\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1))\n .join(\" \");\n const skillContent = [\n \"---\",\n `name: ${skillName}`,\n `description: \"Extracted from learning ${learningId}. Replace with a concise description.\"`,\n \"---\",\n \"\",\n `# ${skillTitle}`,\n \"\",\n \"## Why\",\n summary,\n \"\",\n \"## When To Use\",\n \"- [TODO] Define trigger conditions\",\n \"\",\n \"## Steps\",\n \"1. [TODO] Add repeatable workflow steps\",\n \"2. [TODO] Add verification steps\",\n \"\",\n \"## Source Learning\",\n `- Learning ID: ${learningId}`,\n `- Source File: .learnings/${sourceFile}`,\n \"\",\n ].join(\"\\n\");\n await writeFile(skillPath, skillContent, \"utf-8\");\n\n const promotedMarker = `**Status**: promoted_to_skill`;\n const skillPathMarker = `- Skill-Path: ${safeOutputDir || \"skills\"}/${skillName}`;\n let updatedEntry = match[0];\n updatedEntry = updatedEntry.includes(\"**Status**:\")\n ? updatedEntry.replace(/\\*\\*Status\\*\\*:\\s*.+/m, promotedMarker)\n : `${updatedEntry.trimEnd()}\\n${promotedMarker}\\n`;\n if (!updatedEntry.includes(\"Skill-Path:\")) {\n updatedEntry = `${updatedEntry.trimEnd()}\\n${skillPathMarker}\\n`;\n }\n const updatedLearningBody = learningBody.replace(match[0], updatedEntry);\n await writeFile(learningsPath, updatedLearningBody, \"utf-8\");\n\n return {\n content: [{ type: \"text\", text: `Extracted skill scaffold to ${safeOutputDir || \"skills\"}/${skillName}/SKILL.md and updated ${learningId}.` }],\n details: {\n action: \"skill_extracted\",\n learningId,\n sourceFile,\n skillPath: `${safeOutputDir || \"skills\"}/${skillName}/SKILL.md`,\n },\n };\n } catch (error) {\n return {\n content: [{ type: \"text\", text: `Failed to extract skill: ${error instanceof Error ? error.message : String(error)}` }],\n details: { error: \"self_improvement_extract_skill_failed\", message: String(error) },\n };\n }\n },\n }),\n { name: \"self_improvement_extract_skill\" }\n );\n}\n\nexport function registerSelfImprovementReviewTool(api: OpenClawPluginApi, context: ToolContext) {\n api.registerTool(\n (toolCtx) => ({\n name: \"self_improvement_review\",\n label: \"Self-Improvement Review\",\n description: \"Summarize governance backlog from .learnings files (pending/high-priority/promoted counts).\",\n parameters: Type.Object({}),\n async execute() {\n try {\n const workspaceDir = resolveWorkspaceDir(toolCtx, context.workspaceDir);\n await ensureSelfImprovementLearningFiles(workspaceDir);\n const learningsDir = join(workspaceDir, \".learnings\");\n const files = [\"LEARNINGS.md\", \"ERRORS.md\"] as const;\n const stats = { pending: 0, high: 0, promoted: 0, total: 0 };\n\n for (const f of files) {\n const content = await readFile(join(learningsDir, f), \"utf-8\").catch(() => \"\");\n stats.total += (content.match(/^## \\[/gm) || []).length;\n stats.pending += (content.match(/\\*\\*Status\\*\\*:\\s*pending/gi) || []).length;\n stats.high += (content.match(/\\*\\*Priority\\*\\*:\\s*(high|critical)/gi) || []).length;\n stats.promoted += (content.match(/\\*\\*Status\\*\\*:\\s*promoted(_to_skill)?/gi) || []).length;\n }\n\n const text = [\n \"Self-Improvement Governance Snapshot:\",\n `- Total entries: ${stats.total}`,\n `- Pending: ${stats.pending}`,\n `- High/Critical: ${stats.high}`,\n `- Promoted: ${stats.promoted}`,\n \"\",\n \"Recommended loop:\",\n \"1) Resolve high-priority pending entries\",\n \"2) Distill reusable rules into AGENTS.md / SOUL.md / TOOLS.md\",\n \"3) Extract repeatable patterns as skills\",\n ].join(\"\\n\");\n\n return {\n content: [{ type: \"text\", text }],\n details: { action: \"review\", stats },\n };\n } catch (error) {\n return {\n content: [{ type: \"text\", text: `Failed to review self-improvement backlog: ${error instanceof Error ? error.message : String(error)}` }],\n details: { error: \"self_improvement_review_failed\", message: String(error) },\n };\n }\n },\n }),\n { name: \"self_improvement_review\" }\n );\n}\n\n// ============================================================================\n// Core Tools (Backward Compatible)\n// ============================================================================\n\nexport function registerMemoryRecallTool(\n api: OpenClawPluginApi,\n context: ToolContext,\n) {\n api.registerTool(\n (toolCtx) => {\n const runtimeContext = resolveToolContext(context, toolCtx);\n return {\n name: \"memory_recall\",\n label: \"Memory Recall\",\n description:\n \"Search through long-term memories using hybrid retrieval (vector + keyword search). Use when you need context about user preferences, past decisions, or previously discussed topics.\",\n parameters: Type.Object({\n query: Type.String({\n description: \"Search query for finding relevant memories\",\n }),\n limit: Type.Optional(\n Type.Number({\n description: \"Max results to return (default: 5, max: 20)\",\n }),\n ),\n scope: Type.Optional(\n Type.String({\n description: \"Specific memory scope to search in (optional)\",\n }),\n ),\n category: Type.Optional(stringEnum(MEMORY_CATEGORIES)),\n }),\n async execute(_toolCallId, params) {\n const {\n query,\n limit = 5,\n scope,\n category,\n } = params as {\n query: string;\n limit?: number;\n scope?: string;\n category?: string;\n };\n\n try {\n const safeLimit = clampInt(limit, 1, 20);\n const agentId = runtimeContext.agentId;\n\n // Determine accessible scopes\n let scopeFilter = runtimeContext.scopeManager.getAccessibleScopes(agentId);\n if (scope) {\n if (runtimeContext.scopeManager.isAccessible(scope, agentId)) {\n scopeFilter = [scope];\n } else {\n return {\n content: [\n { type: \"text\", text: `Access denied to scope: ${scope}` },\n ],\n details: {\n error: \"scope_access_denied\",\n requestedScope: scope,\n },\n };\n }\n }\n\n const results = await retrieveWithRetry(runtimeContext.retriever, {\n query,\n limit: safeLimit,\n scopeFilter,\n category,\n source: \"manual\",\n });\n\n if (results.length === 0) {\n return {\n content: [{ type: \"text\", text: \"No relevant memories found.\" }],\n details: { count: 0, query, scopes: scopeFilter },\n };\n }\n\n const now = Date.now();\n await Promise.allSettled(\n results.map((result) => {\n const meta = parseSmartMetadata(result.entry.metadata, result.entry);\n return runtimeContext.store.patchMetadata(\n result.entry.id,\n {\n access_count: meta.access_count + 1,\n last_accessed_at: now,\n },\n scopeFilter,\n );\n }),\n );\n\n const text = results\n .map((r, i) => {\n const categoryTag = getDisplayCategoryTag(r.entry);\n return `${i + 1}. [${r.entry.id}] [${categoryTag}] ${r.entry.text}`;\n })\n .join(\"\\n\");\n\n return {\n content: [\n {\n type: \"text\",\n text: `Found ${results.length} memories:\\n\\n${text}`,\n },\n ],\n details: {\n count: results.length,\n memories: sanitizeMemoryForSerialization(results),\n query,\n scopes: scopeFilter,\n retrievalMode: runtimeContext.retriever.getConfig().mode,\n },\n };\n } catch (error) {\n return {\n content: [\n {\n type: \"text\",\n text: `Memory recall failed: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n details: { error: \"recall_failed\", message: String(error) },\n };\n }\n },\n };\n },\n { name: \"memory_recall\" },\n );\n}\n\nexport function registerMemoryStoreTool(\n api: OpenClawPluginApi,\n context: ToolContext,\n) {\n api.registerTool(\n (toolCtx) => {\n const runtimeContext = resolveToolContext(context, toolCtx);\n return {\n name: \"memory_store\",\n label: \"Memory Store\",\n description:\n \"Save important information in long-term memory. Use for preferences, facts, decisions, and other notable information.\",\n parameters: Type.Object({\n text: Type.String({ description: \"Information to remember\" }),\n importance: Type.Optional(\n Type.Number({ description: \"Importance score 0-1 (default: 0.7)\" }),\n ),\n category: Type.Optional(stringEnum(MEMORY_CATEGORIES)),\n scope: Type.Optional(\n Type.String({\n description: \"Memory scope (optional, defaults to agent scope)\",\n }),\n ),\n }),\n async execute(_toolCallId, params) {\n const {\n text,\n importance = 0.7,\n category = \"other\",\n scope,\n } = params as {\n text: string;\n importance?: number;\n category?: string;\n scope?: string;\n };\n\n try {\n const agentId = runtimeContext.agentId;\n // Determine target scope\n let targetScope = scope || runtimeContext.scopeManager.getDefaultScope(agentId);\n\n // Validate scope access\n if (!runtimeContext.scopeManager.isAccessible(targetScope, agentId)) {\n return {\n content: [\n {\n type: \"text\",\n text: `Access denied to scope: ${targetScope}`,\n },\n ],\n details: {\n error: \"scope_access_denied\",\n requestedScope: targetScope,\n },\n };\n }\n\n // Reject noise before wasting an embedding API call\n if (isNoise(text)) {\n return {\n content: [\n {\n type: \"text\",\n text: `Skipped: text detected as noise (greeting, boilerplate, or meta-question)`,\n },\n ],\n details: { action: \"noise_filtered\", text: text.slice(0, 60) },\n };\n }\n\n const safeImportance = clamp01(importance, 0.7);\n const vector = await runtimeContext.embedder.embedPassage(text);\n\n // Check for duplicates using raw vector similarity (bypasses importance/recency weighting)\n // Fail-open by design: dedup must never block a legitimate memory write.\n let existing: Awaited<ReturnType<MemoryStore[\"vectorSearch\"]>> = [];\n try {\n existing = await runtimeContext.store.vectorSearch(vector, 1, 0.1, [\n targetScope,\n ]);\n } catch (err) {\n log.warn(\n `duplicate pre-check failed, continue store: ${String(err)}`,\n );\n }\n\n if (existing.length > 0 && existing[0].score > 0.98) {\n return {\n content: [\n {\n type: \"text\",\n text: `Similar memory already exists: \"${existing[0].entry.text}\"`,\n },\n ],\n details: {\n action: \"duplicate\",\n existingId: existing[0].entry.id,\n existingText: existing[0].entry.text,\n existingScope: existing[0].entry.scope,\n similarity: existing[0].score,\n },\n };\n }\n\n const entry = await runtimeContext.store.store({\n text,\n vector,\n importance: safeImportance,\n category: category as any,\n scope: targetScope,\n metadata: stringifySmartMetadata(\n buildSmartMetadata(\n {\n text,\n category: category as any,\n importance: safeImportance,\n },\n {\n l0_abstract: text,\n l1_overview: `- ${text}`,\n l2_content: text,\n },\n ),\n ),\n });\n\n // Dual-write to Markdown mirror if enabled\n if (context.mdMirror) {\n await context.mdMirror(\n { text, category: category as string, scope: targetScope, timestamp: entry.timestamp },\n { source: \"memory_store\", agentId },\n );\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: `Stored: \"${text.slice(0, 100)}${text.length > 100 ? \"...\" : \"\"}\" in scope '${targetScope}'`,\n },\n ],\n details: {\n action: \"created\",\n id: entry.id,\n scope: entry.scope,\n category: entry.category,\n importance: entry.importance,\n },\n };\n } catch (error) {\n return {\n content: [\n {\n type: \"text\",\n text: `Memory storage failed: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n details: { error: \"store_failed\", message: String(error) },\n };\n }\n },\n };\n },\n { name: \"memory_store\" },\n );\n}\n\nexport function registerMemoryForgetTool(\n api: OpenClawPluginApi,\n context: ToolContext,\n) {\n api.registerTool(\n (toolCtx) => {\n const agentId = resolveAgentId((toolCtx as any)?.agentId, context.agentId) ?? \"main\";\n return {\n name: \"memory_forget\",\n label: \"Memory Forget\",\n description:\n \"Delete specific memories. Supports both search-based and direct ID-based deletion.\",\n parameters: Type.Object({\n query: Type.Optional(\n Type.String({ description: \"Search query to find memory to delete\" }),\n ),\n memoryId: Type.Optional(\n Type.String({ description: \"Specific memory ID to delete\" }),\n ),\n scope: Type.Optional(\n Type.String({\n description: \"Scope to search/delete from (optional)\",\n }),\n ),\n }),\n async execute(_toolCallId, params, _signal, _onUpdate, runtimeCtx) {\n const { query, memoryId, scope } = params as {\n query?: string;\n memoryId?: string;\n scope?: string;\n };\n\n try {\n const agentId = resolveRuntimeAgentId(context.agentId, runtimeCtx);\n // Determine accessible scopes\n let scopeFilter = context.scopeManager.getAccessibleScopes(agentId);\n if (scope) {\n if (context.scopeManager.isAccessible(scope, agentId)) {\n scopeFilter = [scope];\n } else {\n return {\n content: [\n { type: \"text\", text: `Access denied to scope: ${scope}` },\n ],\n details: {\n error: \"scope_access_denied\",\n requestedScope: scope,\n },\n };\n }\n }\n\n if (memoryId) {\n const deleted = await context.store.delete(memoryId, scopeFilter);\n if (deleted) {\n return {\n content: [\n { type: \"text\", text: `Memory ${memoryId} forgotten.` },\n ],\n details: { action: \"deleted\", id: memoryId },\n };\n } else {\n return {\n content: [\n {\n type: \"text\",\n text: `Memory ${memoryId} not found or access denied.`,\n },\n ],\n details: { error: \"not_found\", id: memoryId },\n };\n }\n }\n\n if (query) {\n const results = await retrieveWithRetry(context.retriever, {\n query,\n limit: 5,\n scopeFilter,\n });\n\n if (results.length === 0) {\n return {\n content: [\n { type: \"text\", text: \"No matching memories found.\" },\n ],\n details: { found: 0, query },\n };\n }\n\n if (results.length === 1 && results[0].score > 0.9) {\n const deleted = await context.store.delete(\n results[0].entry.id,\n scopeFilter,\n );\n if (deleted) {\n return {\n content: [\n {\n type: \"text\",\n text: `Forgotten: \"${results[0].entry.text}\"`,\n },\n ],\n details: { action: \"deleted\", id: results[0].entry.id },\n };\n }\n }\n\n const list = results\n .map(\n (r) =>\n `- [${r.entry.id.slice(0, 8)}] ${r.entry.text.slice(0, 60)}${r.entry.text.length > 60 ? \"...\" : \"\"}`,\n )\n .join(\"\\n\");\n\n return {\n content: [\n {\n type: \"text\",\n text: `Found ${results.length} candidates. Specify memoryId to delete:\\n${list}`,\n },\n ],\n details: {\n action: \"candidates\",\n candidates: sanitizeMemoryForSerialization(results),\n },\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: \"Provide either 'query' to search for memories or 'memoryId' to delete specific memory.\",\n },\n ],\n details: { error: \"missing_param\" },\n };\n } catch (error) {\n return {\n content: [\n {\n type: \"text\",\n text: `Memory deletion failed: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n details: { error: \"delete_failed\", message: String(error) },\n };\n }\n },\n };\n },\n { name: \"memory_forget\" },\n );\n}\n\n// ============================================================================\n// Update Tool\n// ============================================================================\n\nexport function registerMemoryUpdateTool(\n api: OpenClawPluginApi,\n context: ToolContext,\n) {\n api.registerTool(\n (toolCtx) => {\n const agentId = resolveAgentId((toolCtx as any)?.agentId, context.agentId) ?? \"main\";\n return {\n name: \"memory_update\",\n label: \"Memory Update\",\n description:\n \"Update an existing memory in-place. Preserves original timestamp. Use when correcting outdated info or adjusting importance/category without losing creation date.\",\n parameters: Type.Object({\n memoryId: Type.String({\n description:\n \"ID of the memory to update (full UUID or 8+ char prefix)\",\n }),\n text: Type.Optional(\n Type.String({\n description: \"New text content (triggers re-embedding)\",\n }),\n ),\n importance: Type.Optional(\n Type.Number({ description: \"New importance score 0-1\" }),\n ),\n category: Type.Optional(stringEnum(MEMORY_CATEGORIES)),\n }),\n async execute(_toolCallId, params, _signal, _onUpdate, runtimeCtx) {\n const { memoryId, text, importance, category } = params as {\n memoryId: string;\n text?: string;\n importance?: number;\n category?: string;\n };\n\n try {\n if (!text && importance === undefined && !category) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Nothing to update. Provide at least one of: text, importance, category.\",\n },\n ],\n details: { error: \"no_updates\" },\n };\n }\n\n // Determine accessible scopes\n const agentId = resolveRuntimeAgentId(context.agentId, runtimeCtx);\n const scopeFilter = context.scopeManager.getAccessibleScopes(agentId);\n\n // Resolve memoryId: if it doesn't look like a UUID, try search\n let resolvedId = memoryId;\n const uuidLike = /^[0-9a-f]{8}(-[0-9a-f]{4}){0,4}/i.test(memoryId);\n if (!uuidLike) {\n // Treat as search query\n const results = await retrieveWithRetry(context.retriever, {\n query: memoryId,\n limit: 3,\n scopeFilter,\n });\n if (results.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `No memory found matching \"${memoryId}\".`,\n },\n ],\n details: { error: \"not_found\", query: memoryId },\n };\n }\n if (results.length === 1 || results[0].score > 0.85) {\n resolvedId = results[0].entry.id;\n } else {\n const list = results\n .map(\n (r) =>\n `- [${r.entry.id.slice(0, 8)}] ${r.entry.text.slice(0, 60)}${r.entry.text.length > 60 ? \"...\" : \"\"}`,\n )\n .join(\"\\n\");\n return {\n content: [\n {\n type: \"text\",\n text: `Multiple matches. Specify memoryId:\\n${list}`,\n },\n ],\n details: {\n action: \"candidates\",\n candidates: sanitizeMemoryForSerialization(results),\n },\n };\n }\n }\n\n // If text changed, re-embed; reject noise\n let newVector: number[] | undefined;\n if (text) {\n if (isNoise(text)) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Skipped: updated text detected as noise\",\n },\n ],\n details: { action: \"noise_filtered\" },\n };\n }\n newVector = await context.embedder.embedPassage(text);\n }\n\n const updates: Record<string, any> = {};\n if (text) updates.text = text;\n if (newVector) updates.vector = newVector;\n if (importance !== undefined)\n updates.importance = clamp01(importance, 0.7);\n if (category) updates.category = category;\n\n const updated = await context.store.update(\n resolvedId,\n updates,\n scopeFilter,\n );\n\n if (!updated) {\n return {\n content: [\n {\n type: \"text\",\n text: `Memory ${resolvedId.slice(0, 8)}... not found or access denied.`,\n },\n ],\n details: { error: \"not_found\", id: resolvedId },\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: `Updated memory ${updated.id.slice(0, 8)}...: \"${updated.text.slice(0, 80)}${updated.text.length > 80 ? \"...\" : \"\"}\"`,\n },\n ],\n details: {\n action: \"updated\",\n id: updated.id,\n scope: updated.scope,\n category: updated.category,\n importance: updated.importance,\n fieldsUpdated: Object.keys(updates),\n },\n };\n } catch (error) {\n return {\n content: [\n {\n type: \"text\",\n text: `Memory update failed: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n details: { error: \"update_failed\", message: String(error) },\n };\n }\n },\n };\n },\n { name: \"memory_update\" },\n );\n}\n\n// ============================================================================\n// Management Tools (Optional)\n// ============================================================================\n\nexport function registerMemoryStatsTool(\n api: OpenClawPluginApi,\n context: ToolContext,\n) {\n api.registerTool(\n (toolCtx) => {\n const agentId = resolveAgentId((toolCtx as any)?.agentId, context.agentId) ?? \"main\";\n return {\n name: \"memory_stats\",\n label: \"Memory Statistics\",\n description: \"Get statistics about memory usage, scopes, and categories.\",\n parameters: Type.Object({\n scope: Type.Optional(\n Type.String({\n description: \"Specific scope to get stats for (optional)\",\n }),\n ),\n }),\n async execute(_toolCallId, params, _signal, _onUpdate, runtimeCtx) {\n const { scope } = params as { scope?: string };\n\n try {\n const agentId = resolveRuntimeAgentId(context.agentId, runtimeCtx);\n // Determine accessible scopes\n let scopeFilter = context.scopeManager.getAccessibleScopes(agentId);\n if (scope) {\n if (context.scopeManager.isAccessible(scope, agentId)) {\n scopeFilter = [scope];\n } else {\n return {\n content: [\n { type: \"text\", text: `Access denied to scope: ${scope}` },\n ],\n details: {\n error: \"scope_access_denied\",\n requestedScope: scope,\n },\n };\n }\n }\n\n const stats = await context.store.stats(scopeFilter);\n const scopeManagerStats = context.scopeManager.getStats();\n const retrievalConfig = context.retriever.getConfig();\n\n const text = [\n `Memory Statistics:`,\n `\u2022 Total memories: ${stats.totalCount}`,\n `\u2022 Available scopes: ${scopeManagerStats.totalScopes}`,\n `\u2022 Retrieval mode: ${retrievalConfig.mode}`,\n `\u2022 FTS support: ${context.store.hasFtsSupport ? \"Yes\" : \"No\"}`,\n ``,\n `Memories by scope:`,\n ...Object.entries(stats.scopeCounts).map(\n ([s, count]) => ` \u2022 ${s}: ${count}`,\n ),\n ``,\n `Memories by category:`,\n ...Object.entries(stats.categoryCounts).map(\n ([c, count]) => ` \u2022 ${c}: ${count}`,\n ),\n ].join(\"\\n\");\n\n return {\n content: [{ type: \"text\", text }],\n details: {\n stats,\n scopeManagerStats,\n retrievalConfig: {\n ...retrievalConfig,\n rerankApiKey: retrievalConfig.rerankApiKey ? \"***\" : undefined,\n },\n hasFtsSupport: context.store.hasFtsSupport,\n },\n };\n } catch (error) {\n return {\n content: [\n {\n type: \"text\",\n text: `Failed to get memory stats: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n details: { error: \"stats_failed\", message: String(error) },\n };\n }\n },\n };\n },\n { name: \"memory_stats\" },\n );\n}\n\nexport function registerMemoryListTool(\n api: OpenClawPluginApi,\n context: ToolContext,\n) {\n api.registerTool(\n (toolCtx) => {\n const agentId = resolveAgentId((toolCtx as any)?.agentId, context.agentId) ?? \"main\";\n return {\n name: \"memory_list\",\n label: \"Memory List\",\n description:\n \"List recent memories with optional filtering by scope and category.\",\n parameters: Type.Object({\n limit: Type.Optional(\n Type.Number({\n description: \"Max memories to list (default: 10, max: 50)\",\n }),\n ),\n scope: Type.Optional(\n Type.String({ description: \"Filter by specific scope (optional)\" }),\n ),\n category: Type.Optional(stringEnum(MEMORY_CATEGORIES)),\n offset: Type.Optional(\n Type.Number({\n description: \"Number of memories to skip (default: 0)\",\n }),\n ),\n }),\n async execute(_toolCallId, params, _signal, _onUpdate, runtimeCtx) {\n const {\n limit = 10,\n scope,\n category,\n offset = 0,\n } = params as {\n limit?: number;\n scope?: string;\n category?: string;\n offset?: number;\n };\n\n try {\n const safeLimit = clampInt(limit, 1, 50);\n const safeOffset = clampInt(offset, 0, 1000);\n const agentId = resolveRuntimeAgentId(context.agentId, runtimeCtx);\n\n // Determine accessible scopes\n let scopeFilter = context.scopeManager.getAccessibleScopes(agentId);\n if (scope) {\n if (context.scopeManager.isAccessible(scope, agentId)) {\n scopeFilter = [scope];\n } else {\n return {\n content: [\n { type: \"text\", text: `Access denied to scope: ${scope}` },\n ],\n details: {\n error: \"scope_access_denied\",\n requestedScope: scope,\n },\n };\n }\n }\n\n const entries = await context.store.list(\n scopeFilter,\n category,\n safeLimit,\n safeOffset,\n );\n\n if (entries.length === 0) {\n return {\n content: [{ type: \"text\", text: \"No memories found.\" }],\n details: {\n count: 0,\n filters: {\n scope,\n category,\n limit: safeLimit,\n offset: safeOffset,\n },\n },\n };\n }\n\n const text = entries\n .map((entry, i) => {\n const date = new Date(entry.timestamp)\n .toISOString()\n .split(\"T\")[0];\n const categoryTag = getDisplayCategoryTag(entry);\n return `${safeOffset + i + 1}. [${entry.id}] [${categoryTag}] ${entry.text.slice(0, 100)}${entry.text.length > 100 ? \"...\" : \"\"} (${date})`;\n })\n .join(\"\\n\");\n\n return {\n content: [\n {\n type: \"text\",\n text: `Recent memories (showing ${entries.length}):\\n\\n${text}`,\n },\n ],\n details: {\n count: entries.length,\n memories: entries.map((e) => ({\n id: e.id,\n text: e.text,\n category: getDisplayCategoryTag(e),\n rawCategory: e.category,\n scope: e.scope,\n importance: e.importance,\n timestamp: e.timestamp,\n })),\n filters: {\n scope,\n category,\n limit: safeLimit,\n offset: safeOffset,\n },\n },\n };\n } catch (error) {\n return {\n content: [\n {\n type: \"text\",\n text: `Failed to list memories: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n details: { error: \"list_failed\", message: String(error) },\n };\n }\n },\n };\n },\n { name: \"memory_list\" },\n );\n}\n\n// ============================================================================\n// Tool Registration Helper\n// ============================================================================\n\nexport function registerAllMemoryTools(\n api: OpenClawPluginApi,\n context: ToolContext,\n options: {\n enableManagementTools?: boolean;\n enableSelfImprovementTools?: boolean;\n } = {},\n) {\n // Core tools (always enabled)\n registerMemoryRecallTool(api, context);\n registerMemoryStoreTool(api, context);\n registerMemoryForgetTool(api, context);\n registerMemoryUpdateTool(api, context);\n\n // Management tools (optional)\n if (options.enableManagementTools) {\n registerMemoryStatsTool(api, context);\n registerMemoryListTool(api, context);\n }\n if (options.enableSelfImprovementTools !== false) {\n registerSelfImprovementLogTool(api, context);\n if (options.enableManagementTools) {\n registerSelfImprovementExtractSkillTool(api, context);\n registerSelfImprovementReviewTool(api, context);\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["agentId"]
|
|
7
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"wal-recovery.d.ts","sourceRoot":"","sources":["../../src/wal-recovery.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAkBH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAUD,wBAAsB,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAI9D;AAED,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAahE;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAc5E;AAMD;;;GAGG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAkF3F"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/wal-recovery.ts"],
|
|
4
|
-
"sourcesContent": ["// SPDX-License-Identifier: LicenseRef-Mnemo-Pro\n/**\n * Graphiti Write-Ahead Log (WAL) + Recovery\n *\n * Ensures Graphiti writes survive transient failures by logging pending writes\n * to a JSONL file. On plugin startup, pending entries older than 1 hour are\n * retried automatically.\n */\n\nimport { appendFile, readFile, mkdir } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, dirname } from \"node:path\";\nimport { log } from \"./logger.js\";\n\n// ============================================================================\n// WAL Path\n// ============================================================================\n\nconst WAL_PATH = join(homedir(), \".openclaw\", \"memory\", \"graphiti-wal.jsonl\");\n\n// ============================================================================\n// WAL Entry Types\n// ============================================================================\n\nexport interface WalEntry {\n ts: string;\n action: \"write\";\n text: string;\n scope: string;\n category: string;\n groupId: string;\n importance: number;\n status: \"pending\" | \"committed\" | \"failed\";\n error?: string;\n}\n\n// ============================================================================\n// WAL Writer\n// ============================================================================\n\nasync function ensureWalDir(): Promise<void> {\n await mkdir(dirname(WAL_PATH), { recursive: true });\n}\n\nexport async function walAppend(entry: WalEntry): Promise<void> {\n await ensureWalDir();\n const line = JSON.stringify(entry) + \"\\n\";\n await appendFile(WAL_PATH, line, \"utf8\");\n}\n\nexport async function walMarkCommitted(ts: string): Promise<void> {\n const entry: WalEntry = {\n ts,\n action: \"write\",\n text: \"\",\n scope: \"\",\n category: \"\",\n groupId: \"\",\n importance: 0,\n status: \"committed\",\n };\n await ensureWalDir();\n await appendFile(WAL_PATH, JSON.stringify(entry) + \"\\n\", \"utf8\");\n}\n\nexport async function walMarkFailed(ts: string, error: string): Promise<void> {\n const entry: WalEntry = {\n ts,\n action: \"write\",\n text: \"\",\n scope: \"\",\n category: \"\",\n groupId: \"\",\n importance: 0,\n status: \"failed\",\n error,\n };\n await ensureWalDir();\n await appendFile(WAL_PATH, JSON.stringify(entry) + \"\\n\", \"utf8\");\n}\n\n// ============================================================================\n// WAL Recovery\n// ============================================================================\n\n/**\n * Scan the WAL file for entries with status=pending whose ts > 1 hour ago.\n * Retry writing them to Graphiti and mark as committed or failed.\n */\nexport async function recoverPendingWrites(): Promise<{ recovered: number; failed: number }> {\n if (!existsSync(WAL_PATH)) {\n return { recovered: 0, failed: 0 };\n }\n\n let raw: string;\n try {\n raw = await readFile(WAL_PATH, \"utf8\");\n } catch {\n return { recovered: 0, failed: 0 };\n }\n\n const lines = raw.split(\"\\n\").filter((l) => l.trim().length > 0);\n\n // Build a map of latest status per ts\n const statusMap = new Map<string, WalEntry>();\n for (const line of lines) {\n try {\n const entry = JSON.parse(line) as WalEntry;\n // Later entries for the same ts override earlier ones\n const existing = statusMap.get(entry.ts);\n if (!existing || entry.status !== \"pending\") {\n statusMap.set(entry.ts, entry);\n }\n } catch {\n // Skip malformed lines\n }\n }\n\n // Find pending entries older than 1 hour\n const oneHourAgo = Date.now() - 60 * 60 * 1000;\n const pending: WalEntry[] = [];\n for (const entry of statusMap.values()) {\n if (entry.status === \"pending\") {\n const entryTime = new Date(entry.ts).getTime();\n if (entryTime < oneHourAgo) {\n pending.push(entry);\n }\n }\n }\n\n if (pending.length === 0) {\n return { recovered: 0, failed: 0 };\n }\n\n const graphitiBase = process.env.GRAPHITI_BASE_URL || \"http://127.0.0.1:18799\";\n let recovered = 0;\n let failed = 0;\n\n for (const entry of pending) {\n try {\n const response = await fetch(`${graphitiBase}/episodes`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n text: `[${entry.category}] ${entry.text}`,\n group_id: entry.groupId,\n reference_time: entry.ts,\n source: `lancedb-pro-store-${entry.groupId}`,\n category: entry.category,\n }),\n signal: AbortSignal.timeout(15000),\n });\n\n if (response.ok) {\n await walMarkCommitted(entry.ts);\n recovered++;\n } else {\n await walMarkFailed(entry.ts, `HTTP ${response.status}`);\n failed++;\n }\n } catch (err) {\n await walMarkFailed(entry.ts, String(err));\n failed++;\n }\n }\n\n log.info(\n `WAL recovery \u2014 recovered=${recovered}, failed=${failed}, total_pending=${pending.length}`,\n );\n\n return { recovered, failed };\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|