@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.
Files changed (191) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +321 -0
  3. package/dist/cli.d.ts +0 -1
  4. package/dist/cli.js +0 -1
  5. package/dist/index.d.ts +0 -115
  6. package/dist/index.js +1 -6
  7. package/dist/src/access-tracker.d.ts +0 -1
  8. package/dist/src/access-tracker.js +0 -1
  9. package/dist/src/adapters/chroma.d.ts +0 -1
  10. package/dist/src/adapters/chroma.js +0 -1
  11. package/dist/src/adapters/lancedb.d.ts +0 -1
  12. package/dist/src/adapters/lancedb.js +0 -1
  13. package/dist/src/adapters/pgvector.d.ts +0 -1
  14. package/dist/src/adapters/pgvector.js +0 -1
  15. package/dist/src/adapters/qdrant.d.ts +0 -1
  16. package/dist/src/adapters/qdrant.js +0 -1
  17. package/dist/src/adaptive-retrieval.d.ts +0 -1
  18. package/dist/src/adaptive-retrieval.js +0 -1
  19. package/dist/src/audit-log.d.ts +0 -1
  20. package/dist/src/audit-log.js +0 -1
  21. package/dist/src/chunker.d.ts +0 -1
  22. package/dist/src/chunker.js +0 -1
  23. package/dist/src/config.d.ts +0 -1
  24. package/dist/src/config.js +0 -1
  25. package/dist/src/decay-engine.d.ts +0 -1
  26. package/dist/src/decay-engine.js +0 -1
  27. package/dist/src/embedder.d.ts +0 -1
  28. package/dist/src/embedder.js +0 -1
  29. package/dist/src/extraction-prompts.d.ts +0 -1
  30. package/dist/src/extraction-prompts.js +0 -1
  31. package/dist/src/license.d.ts +0 -1
  32. package/dist/src/license.js +2 -6
  33. package/dist/src/llm-client.d.ts +0 -1
  34. package/dist/src/llm-client.js +0 -1
  35. package/dist/src/logger.d.ts +0 -1
  36. package/dist/src/logger.js +0 -1
  37. package/dist/src/mcp-server.d.ts +0 -1
  38. package/dist/src/mcp-server.js +0 -1
  39. package/dist/src/memory-categories.d.ts +0 -1
  40. package/dist/src/memory-categories.js +0 -1
  41. package/dist/src/memory-upgrader.d.ts +0 -1
  42. package/dist/src/memory-upgrader.js +0 -1
  43. package/dist/src/migrate.d.ts +0 -1
  44. package/dist/src/migrate.js +0 -1
  45. package/dist/src/mnemo.d.ts +7 -1
  46. package/dist/src/mnemo.js +19 -7
  47. package/dist/src/noise-filter.d.ts +0 -1
  48. package/dist/src/noise-filter.js +0 -1
  49. package/dist/src/noise-prototypes.d.ts +0 -1
  50. package/dist/src/noise-prototypes.js +0 -1
  51. package/dist/src/observability.d.ts +0 -1
  52. package/dist/src/observability.js +0 -1
  53. package/dist/src/query-tracker.d.ts +0 -1
  54. package/dist/src/query-tracker.js +0 -1
  55. package/dist/src/reflection-event-store.d.ts +0 -1
  56. package/dist/src/reflection-event-store.js +0 -1
  57. package/dist/src/reflection-item-store.d.ts +0 -1
  58. package/dist/src/reflection-item-store.js +0 -1
  59. package/dist/src/reflection-mapped-metadata.d.ts +0 -1
  60. package/dist/src/reflection-mapped-metadata.js +0 -1
  61. package/dist/src/reflection-metadata.d.ts +0 -1
  62. package/dist/src/reflection-metadata.js +0 -1
  63. package/dist/src/reflection-ranking.d.ts +0 -1
  64. package/dist/src/reflection-ranking.js +0 -1
  65. package/dist/src/reflection-retry.d.ts +0 -1
  66. package/dist/src/reflection-retry.js +0 -1
  67. package/dist/src/reflection-slices.d.ts +0 -1
  68. package/dist/src/reflection-slices.js +0 -1
  69. package/dist/src/reflection-store.d.ts +0 -1
  70. package/dist/src/reflection-store.js +0 -1
  71. package/dist/src/resonance-state.d.ts +0 -1
  72. package/dist/src/resonance-state.js +0 -1
  73. package/dist/src/retriever.d.ts +0 -1
  74. package/dist/src/retriever.js +0 -1
  75. package/dist/src/scopes.d.ts +0 -1
  76. package/dist/src/scopes.js +0 -1
  77. package/dist/src/self-improvement-files.d.ts +0 -1
  78. package/dist/src/self-improvement-files.js +0 -1
  79. package/dist/src/semantic-gate.d.ts +0 -1
  80. package/dist/src/semantic-gate.js +0 -1
  81. package/dist/src/session-recovery.d.ts +0 -1
  82. package/dist/src/session-recovery.js +0 -1
  83. package/dist/src/smart-extractor.d.ts +0 -1
  84. package/dist/src/smart-extractor.js +0 -1
  85. package/dist/src/smart-metadata.d.ts +0 -1
  86. package/dist/src/smart-metadata.js +0 -1
  87. package/dist/src/storage-adapter.d.ts +0 -1
  88. package/dist/src/storage-adapter.js +0 -1
  89. package/dist/src/store.d.ts +0 -1
  90. package/dist/src/store.js +0 -1
  91. package/dist/src/tier-manager.d.ts +0 -1
  92. package/dist/src/tier-manager.js +0 -1
  93. package/dist/src/tools.d.ts +0 -1
  94. package/dist/src/tools.js +0 -1
  95. package/dist/src/wal-recovery.d.ts +0 -1
  96. package/dist/src/wal-recovery.js +0 -1
  97. package/package.json +2 -2
  98. package/dist/cli.d.ts.map +0 -1
  99. package/dist/cli.js.map +0 -7
  100. package/dist/index.d.ts.map +0 -1
  101. package/dist/index.js.map +0 -7
  102. package/dist/src/access-tracker.d.ts.map +0 -1
  103. package/dist/src/access-tracker.js.map +0 -7
  104. package/dist/src/adapters/chroma.d.ts.map +0 -1
  105. package/dist/src/adapters/chroma.js.map +0 -7
  106. package/dist/src/adapters/lancedb.d.ts.map +0 -1
  107. package/dist/src/adapters/lancedb.js.map +0 -7
  108. package/dist/src/adapters/pgvector.d.ts.map +0 -1
  109. package/dist/src/adapters/pgvector.js.map +0 -7
  110. package/dist/src/adapters/qdrant.d.ts.map +0 -1
  111. package/dist/src/adapters/qdrant.js.map +0 -7
  112. package/dist/src/adaptive-retrieval.d.ts.map +0 -1
  113. package/dist/src/adaptive-retrieval.js.map +0 -7
  114. package/dist/src/audit-log.d.ts.map +0 -1
  115. package/dist/src/audit-log.js.map +0 -7
  116. package/dist/src/chunker.d.ts.map +0 -1
  117. package/dist/src/chunker.js.map +0 -7
  118. package/dist/src/config.d.ts.map +0 -1
  119. package/dist/src/config.js.map +0 -7
  120. package/dist/src/decay-engine.d.ts.map +0 -1
  121. package/dist/src/decay-engine.js.map +0 -7
  122. package/dist/src/embedder.d.ts.map +0 -1
  123. package/dist/src/embedder.js.map +0 -7
  124. package/dist/src/extraction-prompts.d.ts.map +0 -1
  125. package/dist/src/extraction-prompts.js.map +0 -7
  126. package/dist/src/license.d.ts.map +0 -1
  127. package/dist/src/license.js.map +0 -7
  128. package/dist/src/llm-client.d.ts.map +0 -1
  129. package/dist/src/llm-client.js.map +0 -7
  130. package/dist/src/logger.d.ts.map +0 -1
  131. package/dist/src/logger.js.map +0 -7
  132. package/dist/src/mcp-server.d.ts.map +0 -1
  133. package/dist/src/mcp-server.js.map +0 -7
  134. package/dist/src/memory-categories.d.ts.map +0 -1
  135. package/dist/src/memory-categories.js.map +0 -7
  136. package/dist/src/memory-upgrader.d.ts.map +0 -1
  137. package/dist/src/memory-upgrader.js.map +0 -7
  138. package/dist/src/migrate.d.ts.map +0 -1
  139. package/dist/src/migrate.js.map +0 -7
  140. package/dist/src/mnemo.d.ts.map +0 -1
  141. package/dist/src/mnemo.js.map +0 -7
  142. package/dist/src/noise-filter.d.ts.map +0 -1
  143. package/dist/src/noise-filter.js.map +0 -7
  144. package/dist/src/noise-prototypes.d.ts.map +0 -1
  145. package/dist/src/noise-prototypes.js.map +0 -7
  146. package/dist/src/observability.d.ts.map +0 -1
  147. package/dist/src/observability.js.map +0 -7
  148. package/dist/src/query-tracker.d.ts.map +0 -1
  149. package/dist/src/query-tracker.js.map +0 -7
  150. package/dist/src/reflection-event-store.d.ts.map +0 -1
  151. package/dist/src/reflection-event-store.js.map +0 -7
  152. package/dist/src/reflection-item-store.d.ts.map +0 -1
  153. package/dist/src/reflection-item-store.js.map +0 -7
  154. package/dist/src/reflection-mapped-metadata.d.ts.map +0 -1
  155. package/dist/src/reflection-mapped-metadata.js.map +0 -7
  156. package/dist/src/reflection-metadata.d.ts.map +0 -1
  157. package/dist/src/reflection-metadata.js.map +0 -7
  158. package/dist/src/reflection-ranking.d.ts.map +0 -1
  159. package/dist/src/reflection-ranking.js.map +0 -7
  160. package/dist/src/reflection-retry.d.ts.map +0 -1
  161. package/dist/src/reflection-retry.js.map +0 -7
  162. package/dist/src/reflection-slices.d.ts.map +0 -1
  163. package/dist/src/reflection-slices.js.map +0 -7
  164. package/dist/src/reflection-store.d.ts.map +0 -1
  165. package/dist/src/reflection-store.js.map +0 -7
  166. package/dist/src/resonance-state.d.ts.map +0 -1
  167. package/dist/src/resonance-state.js.map +0 -7
  168. package/dist/src/retriever.d.ts.map +0 -1
  169. package/dist/src/retriever.js.map +0 -7
  170. package/dist/src/scopes.d.ts.map +0 -1
  171. package/dist/src/scopes.js.map +0 -7
  172. package/dist/src/self-improvement-files.d.ts.map +0 -1
  173. package/dist/src/self-improvement-files.js.map +0 -7
  174. package/dist/src/semantic-gate.d.ts.map +0 -1
  175. package/dist/src/semantic-gate.js.map +0 -7
  176. package/dist/src/session-recovery.d.ts.map +0 -1
  177. package/dist/src/session-recovery.js.map +0 -7
  178. package/dist/src/smart-extractor.d.ts.map +0 -1
  179. package/dist/src/smart-extractor.js.map +0 -7
  180. package/dist/src/smart-metadata.d.ts.map +0 -1
  181. package/dist/src/smart-metadata.js.map +0 -7
  182. package/dist/src/storage-adapter.d.ts.map +0 -1
  183. package/dist/src/storage-adapter.js.map +0 -7
  184. package/dist/src/store.d.ts.map +0 -1
  185. package/dist/src/store.js.map +0 -7
  186. package/dist/src/tier-manager.d.ts.map +0 -1
  187. package/dist/src/tier-manager.js.map +0 -7
  188. package/dist/src/tools.d.ts.map +0 -1
  189. package/dist/src/tools.js.map +0 -7
  190. package/dist/src/wal-recovery.d.ts.map +0 -1
  191. package/dist/src/wal-recovery.js.map +0 -7
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/reflection-store.ts"],
4
- "sourcesContent": ["// SPDX-License-Identifier: LicenseRef-Mnemo-Pro\nimport type { MemoryEntry, MemorySearchResult } from \"./store.js\";\nimport {\n extractReflectionSliceItems,\n extractReflectionSlices,\n sanitizeReflectionSliceLines,\n type ReflectionSlices,\n} from \"./reflection-slices.js\";\nimport { parseReflectionMetadata } from \"./reflection-metadata.js\";\nimport { buildReflectionEventPayload, createReflectionEventId } from \"./reflection-event-store.js\";\nimport {\n buildReflectionItemPayloads,\n getReflectionItemDecayDefaults,\n REFLECTION_DERIVED_DECAY_K,\n REFLECTION_DERIVED_DECAY_MIDPOINT_DAYS,\n REFLECTION_INVARIANT_DECAY_K,\n REFLECTION_INVARIANT_DECAY_MIDPOINT_DAYS,\n} from \"./reflection-item-store.js\";\nimport { getReflectionMappedDecayDefaults, type ReflectionMappedKind } from \"./reflection-mapped-metadata.js\";\nimport { computeReflectionScore, normalizeReflectionLineForAggregation } from \"./reflection-ranking.js\";\n\nexport const REFLECTION_DERIVE_LOGISTIC_MIDPOINT_DAYS = 3;\nexport const REFLECTION_DERIVE_LOGISTIC_K = 1.2;\nexport const REFLECTION_DERIVE_FALLBACK_BASE_WEIGHT = 0.35;\n\nexport const DEFAULT_REFLECTION_DERIVED_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1000;\nexport const DEFAULT_REFLECTION_MAPPED_MAX_AGE_MS = 60 * 24 * 60 * 60 * 1000;\n\ntype ReflectionStoreKind = \"event\" | \"item-invariant\" | \"item-derived\" | \"combined-legacy\";\n\ntype ReflectionErrorSignalLike = {\n signatureHash: string;\n};\n\ninterface ReflectionStorePayload {\n text: string;\n metadata: Record<string, unknown>;\n kind: ReflectionStoreKind;\n}\n\ninterface BuildReflectionStorePayloadsParams {\n reflectionText: string;\n sessionKey: string;\n sessionId: string;\n agentId: string;\n command: string;\n scope: string;\n toolErrorSignals: ReflectionErrorSignalLike[];\n runAt: number;\n usedFallback: boolean;\n eventId?: string;\n sourceReflectionPath?: string;\n writeLegacyCombined?: boolean;\n}\n\nexport function buildReflectionStorePayloads(params: BuildReflectionStorePayloadsParams): {\n eventId: string;\n slices: ReflectionSlices;\n payloads: ReflectionStorePayload[];\n} {\n const slices = extractReflectionSlices(params.reflectionText);\n const eventId = params.eventId || createReflectionEventId({\n runAt: params.runAt,\n sessionKey: params.sessionKey,\n sessionId: params.sessionId,\n agentId: params.agentId,\n command: params.command,\n });\n\n const payloads: ReflectionStorePayload[] = [\n buildReflectionEventPayload({\n eventId,\n scope: params.scope,\n sessionKey: params.sessionKey,\n sessionId: params.sessionId,\n agentId: params.agentId,\n command: params.command,\n toolErrorSignals: params.toolErrorSignals,\n runAt: params.runAt,\n usedFallback: params.usedFallback,\n sourceReflectionPath: params.sourceReflectionPath,\n }),\n ];\n\n const itemPayloads = buildReflectionItemPayloads({\n items: extractReflectionSliceItems(params.reflectionText),\n eventId,\n agentId: params.agentId,\n sessionKey: params.sessionKey,\n sessionId: params.sessionId,\n runAt: params.runAt,\n usedFallback: params.usedFallback,\n toolErrorSignals: params.toolErrorSignals,\n sourceReflectionPath: params.sourceReflectionPath,\n });\n payloads.push(...itemPayloads);\n\n if (params.writeLegacyCombined !== false && (slices.invariants.length > 0 || slices.derived.length > 0)) {\n payloads.push(buildLegacyCombinedPayload({\n slices,\n scope: params.scope,\n sessionKey: params.sessionKey,\n sessionId: params.sessionId,\n agentId: params.agentId,\n command: params.command,\n toolErrorSignals: params.toolErrorSignals,\n runAt: params.runAt,\n usedFallback: params.usedFallback,\n sourceReflectionPath: params.sourceReflectionPath,\n }));\n }\n\n return { eventId, slices, payloads };\n}\n\nfunction buildLegacyCombinedPayload(params: {\n slices: ReflectionSlices;\n sessionKey: string;\n sessionId: string;\n agentId: string;\n command: string;\n scope: string;\n toolErrorSignals: ReflectionErrorSignalLike[];\n runAt: number;\n usedFallback: boolean;\n sourceReflectionPath?: string;\n}): ReflectionStorePayload {\n const dateYmd = new Date(params.runAt).toISOString().split(\"T\")[0];\n const deriveQuality = computeDerivedLineQuality(params.slices.derived.length);\n const deriveBaseWeight = params.usedFallback ? REFLECTION_DERIVE_FALLBACK_BASE_WEIGHT : 1;\n\n return {\n kind: \"combined-legacy\",\n text: [\n `reflection \u00B7 ${params.scope} \u00B7 ${dateYmd}`,\n `Session Reflection (${new Date(params.runAt).toISOString()})`,\n `Session Key: ${params.sessionKey}`,\n `Session ID: ${params.sessionId}`,\n \"\",\n \"Invariants:\",\n ...(params.slices.invariants.length > 0 ? params.slices.invariants.map((x) => `- ${x}`) : [\"- (none captured)\"]),\n \"\",\n \"Derived:\",\n ...(params.slices.derived.length > 0 ? params.slices.derived.map((x) => `- ${x}`) : [\"- (none captured)\"]),\n ].join(\"\\n\"),\n metadata: {\n type: \"memory-reflection\",\n stage: \"reflect-store\",\n reflectionVersion: 3,\n sessionKey: params.sessionKey,\n sessionId: params.sessionId,\n agentId: params.agentId,\n command: params.command,\n storedAt: params.runAt,\n invariants: params.slices.invariants,\n derived: params.slices.derived,\n usedFallback: params.usedFallback,\n errorSignals: params.toolErrorSignals.map((s) => s.signatureHash),\n decayModel: \"logistic\",\n decayMidpointDays: REFLECTION_DERIVE_LOGISTIC_MIDPOINT_DAYS,\n decayK: REFLECTION_DERIVE_LOGISTIC_K,\n deriveBaseWeight,\n deriveQuality,\n deriveSource: params.usedFallback ? \"fallback\" : \"normal\",\n ...(params.sourceReflectionPath ? { sourceReflectionPath: params.sourceReflectionPath } : {}),\n },\n };\n}\n\ninterface ReflectionStoreDeps {\n embedPassage: (text: string) => Promise<number[]>;\n vectorSearch: (\n vector: number[],\n limit?: number,\n minScore?: number,\n scopeFilter?: string[]\n ) => Promise<MemorySearchResult[]>;\n store: (entry: Omit<MemoryEntry, \"id\" | \"timestamp\">) => Promise<MemoryEntry>;\n}\n\ninterface StoreReflectionToLanceDBParams extends BuildReflectionStorePayloadsParams, ReflectionStoreDeps {\n dedupeThreshold?: number;\n}\n\nexport async function storeReflectionToLanceDB(params: StoreReflectionToLanceDBParams): Promise<{\n stored: boolean;\n eventId: string;\n slices: ReflectionSlices;\n storedKinds: ReflectionStoreKind[];\n}> {\n const { eventId, slices, payloads } = buildReflectionStorePayloads(params);\n const storedKinds: ReflectionStoreKind[] = [];\n const dedupeThreshold = Number.isFinite(params.dedupeThreshold) ? Number(params.dedupeThreshold) : 0.97;\n\n for (const payload of payloads) {\n const vector = await params.embedPassage(payload.text);\n\n if (payload.kind === \"combined-legacy\") {\n const existing = await params.vectorSearch(vector, 1, 0.1, [params.scope]);\n if (existing.length > 0 && existing[0].score > dedupeThreshold) {\n continue;\n }\n }\n\n await params.store({\n text: payload.text,\n vector,\n category: \"reflection\",\n scope: params.scope,\n importance: resolveReflectionImportance(payload.kind),\n metadata: JSON.stringify(payload.metadata),\n });\n storedKinds.push(payload.kind);\n }\n\n return { stored: storedKinds.length > 0, eventId, slices, storedKinds };\n}\n\nfunction resolveReflectionImportance(kind: ReflectionStoreKind): number {\n if (kind === \"event\") return 0.55;\n if (kind === \"item-invariant\") return 0.82;\n if (kind === \"item-derived\") return 0.78;\n return 0.75;\n}\n\nexport interface LoadReflectionSlicesParams {\n entries: MemoryEntry[];\n agentId: string;\n now?: number;\n deriveMaxAgeMs?: number;\n invariantMaxAgeMs?: number;\n}\n\nexport function loadAgentReflectionSlicesFromEntries(params: LoadReflectionSlicesParams): {\n invariants: string[];\n derived: string[];\n} {\n const now = Number.isFinite(params.now) ? Number(params.now) : Date.now();\n const deriveMaxAgeMs = Number.isFinite(params.deriveMaxAgeMs)\n ? Math.max(0, Number(params.deriveMaxAgeMs))\n : DEFAULT_REFLECTION_DERIVED_MAX_AGE_MS;\n const invariantMaxAgeMs = Number.isFinite(params.invariantMaxAgeMs)\n ? Math.max(0, Number(params.invariantMaxAgeMs))\n : undefined;\n\n const reflectionRows = params.entries\n .map((entry) => ({ entry, metadata: parseReflectionMetadata(entry.metadata) }))\n .filter(({ metadata }) => isReflectionMetadataType(metadata.type) && isOwnedByAgent(metadata, params.agentId))\n .sort((a, b) => b.entry.timestamp - a.entry.timestamp)\n .slice(0, 160);\n\n const itemRows = reflectionRows.filter(({ metadata }) => metadata.type === \"memory-reflection-item\");\n const legacyRows = reflectionRows.filter(({ metadata }) => metadata.type === \"memory-reflection\");\n\n const invariantCandidates = buildInvariantCandidates(itemRows, legacyRows);\n const derivedCandidates = buildDerivedCandidates(itemRows, legacyRows);\n\n const invariants = rankReflectionLines(invariantCandidates, {\n now,\n maxAgeMs: invariantMaxAgeMs,\n limit: 8,\n });\n\n const derived = rankReflectionLines(derivedCandidates, {\n now,\n maxAgeMs: deriveMaxAgeMs,\n limit: 10,\n });\n\n return { invariants, derived };\n}\n\ntype WeightedLineCandidate = {\n line: string;\n timestamp: number;\n midpointDays: number;\n k: number;\n baseWeight: number;\n quality: number;\n usedFallback: boolean;\n};\n\nfunction buildInvariantCandidates(\n itemRows: Array<{ entry: MemoryEntry; metadata: Record<string, unknown> }>,\n legacyRows: Array<{ entry: MemoryEntry; metadata: Record<string, unknown> }>\n): WeightedLineCandidate[] {\n const itemCandidates = itemRows\n .filter(({ metadata }) => metadata.itemKind === \"invariant\")\n .flatMap(({ entry, metadata }) => {\n const lines = sanitizeReflectionSliceLines([entry.text]);\n if (lines.length === 0) return [];\n\n const defaults = getReflectionItemDecayDefaults(\"invariant\");\n const timestamp = metadataTimestamp(metadata, entry.timestamp);\n return lines.map((line) => ({\n line,\n timestamp,\n midpointDays: readPositiveNumber(metadata.decayMidpointDays, defaults.midpointDays),\n k: readPositiveNumber(metadata.decayK, defaults.k),\n baseWeight: readPositiveNumber(metadata.baseWeight, defaults.baseWeight),\n quality: readClampedNumber(metadata.quality, defaults.quality, 0.2, 1),\n usedFallback: metadata.usedFallback === true,\n }));\n });\n\n if (itemCandidates.length > 0) return itemCandidates;\n\n return legacyRows.flatMap(({ entry, metadata }) => {\n const defaults = getReflectionItemDecayDefaults(\"invariant\");\n const timestamp = metadataTimestamp(metadata, entry.timestamp);\n const lines = sanitizeReflectionSliceLines(toStringArray(metadata.invariants));\n return lines.map((line) => ({\n line,\n timestamp,\n midpointDays: defaults.midpointDays,\n k: defaults.k,\n baseWeight: defaults.baseWeight,\n quality: defaults.quality,\n usedFallback: metadata.usedFallback === true,\n }));\n });\n}\n\nfunction buildDerivedCandidates(\n itemRows: Array<{ entry: MemoryEntry; metadata: Record<string, unknown> }>,\n legacyRows: Array<{ entry: MemoryEntry; metadata: Record<string, unknown> }>\n): WeightedLineCandidate[] {\n const itemCandidates = itemRows\n .filter(({ metadata }) => metadata.itemKind === \"derived\")\n .flatMap(({ entry, metadata }) => {\n const lines = sanitizeReflectionSliceLines([entry.text]);\n if (lines.length === 0) return [];\n\n const defaults = getReflectionItemDecayDefaults(\"derived\");\n const timestamp = metadataTimestamp(metadata, entry.timestamp);\n return lines.map((line) => ({\n line,\n timestamp,\n midpointDays: readPositiveNumber(metadata.decayMidpointDays, defaults.midpointDays),\n k: readPositiveNumber(metadata.decayK, defaults.k),\n baseWeight: readPositiveNumber(metadata.baseWeight, defaults.baseWeight),\n quality: readClampedNumber(metadata.quality, defaults.quality, 0.2, 1),\n usedFallback: metadata.usedFallback === true,\n }));\n });\n\n if (itemCandidates.length > 0) return itemCandidates;\n\n return legacyRows.flatMap(({ entry, metadata }) => {\n const timestamp = metadataTimestamp(metadata, entry.timestamp);\n const lines = sanitizeReflectionSliceLines(toStringArray(metadata.derived));\n if (lines.length === 0) return [];\n\n const defaults = {\n midpointDays: REFLECTION_DERIVE_LOGISTIC_MIDPOINT_DAYS,\n k: REFLECTION_DERIVE_LOGISTIC_K,\n baseWeight: resolveLegacyDeriveBaseWeight(metadata),\n quality: computeDerivedLineQuality(lines.length),\n };\n\n return lines.map((line) => ({\n line,\n timestamp,\n midpointDays: readPositiveNumber(metadata.decayMidpointDays, defaults.midpointDays),\n k: readPositiveNumber(metadata.decayK, defaults.k),\n baseWeight: readPositiveNumber(metadata.deriveBaseWeight, defaults.baseWeight),\n quality: readClampedNumber(metadata.deriveQuality, defaults.quality, 0.2, 1),\n usedFallback: metadata.usedFallback === true,\n }));\n });\n}\n\nfunction rankReflectionLines(\n candidates: WeightedLineCandidate[],\n options: { now: number; maxAgeMs?: number; limit: number }\n): string[] {\n type WeightedLine = { line: string; score: number; latestTs: number };\n const lineScores = new Map<string, WeightedLine>();\n\n for (const candidate of candidates) {\n const timestamp = Number.isFinite(candidate.timestamp) ? candidate.timestamp : options.now;\n if (Number.isFinite(options.maxAgeMs) && options.maxAgeMs! >= 0 && options.now - timestamp > options.maxAgeMs!) {\n continue;\n }\n\n const ageDays = Math.max(0, (options.now - timestamp) / 86_400_000);\n const score = computeReflectionScore({\n ageDays,\n midpointDays: candidate.midpointDays,\n k: candidate.k,\n baseWeight: candidate.baseWeight,\n quality: candidate.quality,\n usedFallback: candidate.usedFallback,\n });\n if (!Number.isFinite(score) || score <= 0) continue;\n\n const key = normalizeReflectionLineForAggregation(candidate.line);\n if (!key) continue;\n\n const current = lineScores.get(key);\n if (!current) {\n lineScores.set(key, { line: candidate.line, score, latestTs: timestamp });\n continue;\n }\n\n current.score += score;\n if (timestamp > current.latestTs) {\n current.latestTs = timestamp;\n current.line = candidate.line;\n }\n }\n\n return [...lineScores.values()]\n .sort((a, b) => {\n if (b.score !== a.score) return b.score - a.score;\n if (b.latestTs !== a.latestTs) return b.latestTs - a.latestTs;\n return a.line.localeCompare(b.line);\n })\n .slice(0, options.limit)\n .map((item) => item.line);\n}\n\nfunction isReflectionMetadataType(type: unknown): boolean {\n return type === \"memory-reflection-item\" || type === \"memory-reflection\";\n}\n\nfunction isOwnedByAgent(metadata: Record<string, unknown>, agentId: string): boolean {\n const owner = typeof metadata.agentId === \"string\" ? metadata.agentId.trim() : \"\";\n if (!owner) return true;\n return owner === agentId || owner === \"main\";\n}\n\nfunction toStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value\n .map((item) => String(item).trim())\n .filter(Boolean);\n}\n\nfunction metadataTimestamp(metadata: Record<string, unknown>, fallbackTs: number): number {\n const storedAt = Number(metadata.storedAt);\n if (Number.isFinite(storedAt) && storedAt > 0) return storedAt;\n return Number.isFinite(fallbackTs) ? fallbackTs : Date.now();\n}\n\nfunction readPositiveNumber(value: unknown, fallback: number): number {\n const num = Number(value);\n if (!Number.isFinite(num) || num <= 0) return fallback;\n return num;\n}\n\nfunction readClampedNumber(value: unknown, fallback: number, min: number, max: number): number {\n const num = Number(value);\n const resolved = Number.isFinite(num) ? num : fallback;\n return Math.max(min, Math.min(max, resolved));\n}\n\nexport function computeDerivedLineQuality(nonPlaceholderLineCount: number): number {\n const n = Number.isFinite(nonPlaceholderLineCount) ? Math.max(0, Math.floor(nonPlaceholderLineCount)) : 0;\n if (n <= 0) return 0.2;\n return Math.min(1, 0.55 + Math.min(6, n) * 0.075);\n}\n\nfunction resolveLegacyDeriveBaseWeight(metadata: Record<string, unknown>): number {\n const explicit = Number(metadata.deriveBaseWeight);\n if (Number.isFinite(explicit) && explicit > 0) {\n return Math.max(0.1, Math.min(1.2, explicit));\n }\n if (metadata.usedFallback === true) {\n return REFLECTION_DERIVE_FALLBACK_BASE_WEIGHT;\n }\n return 1;\n}\n\nexport interface LoadReflectionMappedRowsParams {\n entries: MemoryEntry[];\n agentId: string;\n now?: number;\n maxAgeMs?: number;\n maxPerKind?: number;\n}\n\nexport interface ReflectionMappedSlices {\n userModel: string[];\n agentModel: string[];\n lesson: string[];\n decision: string[];\n}\n\nexport function loadReflectionMappedRowsFromEntries(params: LoadReflectionMappedRowsParams): ReflectionMappedSlices {\n const now = Number.isFinite(params.now) ? Number(params.now) : Date.now();\n const maxAgeMs = Number.isFinite(params.maxAgeMs)\n ? Math.max(0, Number(params.maxAgeMs))\n : DEFAULT_REFLECTION_MAPPED_MAX_AGE_MS;\n const maxPerKind = Number.isFinite(params.maxPerKind) ? Math.max(1, Math.floor(Number(params.maxPerKind))) : 10;\n\n type WeightedMapped = {\n text: string;\n mappedKind: ReflectionMappedKind;\n timestamp: number;\n midpointDays: number;\n k: number;\n baseWeight: number;\n quality: number;\n usedFallback: boolean;\n };\n\n const weighted: WeightedMapped[] = params.entries\n .map((entry) => ({ entry, metadata: parseReflectionMetadata(entry.metadata) }))\n .filter(({ metadata }) => metadata.type === \"memory-reflection-mapped\" && isOwnedByAgent(metadata, params.agentId))\n .flatMap(({ entry, metadata }) => {\n const mappedKind = parseMappedKind(metadata.mappedKind);\n if (!mappedKind) return [];\n\n const lines = sanitizeReflectionSliceLines([entry.text]);\n if (lines.length === 0) return [];\n\n const defaults = getReflectionMappedDecayDefaults(mappedKind);\n const timestamp = metadataTimestamp(metadata, entry.timestamp);\n\n return lines.map((line) => ({\n text: line,\n mappedKind,\n timestamp,\n midpointDays: readPositiveNumber(metadata.decayMidpointDays, defaults.midpointDays),\n k: readPositiveNumber(metadata.decayK, defaults.k),\n baseWeight: readPositiveNumber(metadata.baseWeight, defaults.baseWeight),\n quality: readClampedNumber(metadata.quality, defaults.quality, 0.2, 1),\n usedFallback: metadata.usedFallback === true,\n }));\n });\n\n const grouped = new Map<string, { text: string; score: number; latestTs: number; kind: ReflectionMappedKind }>();\n\n for (const item of weighted) {\n if (now - item.timestamp > maxAgeMs) continue;\n const ageDays = Math.max(0, (now - item.timestamp) / 86_400_000);\n const score = computeReflectionScore({\n ageDays,\n midpointDays: item.midpointDays,\n k: item.k,\n baseWeight: item.baseWeight,\n quality: item.quality,\n usedFallback: item.usedFallback,\n });\n if (!Number.isFinite(score) || score <= 0) continue;\n\n const normalized = normalizeReflectionLineForAggregation(item.text);\n if (!normalized) continue;\n\n const key = `${item.mappedKind}::${normalized}`;\n const current = grouped.get(key);\n if (!current) {\n grouped.set(key, { text: item.text, score, latestTs: item.timestamp, kind: item.mappedKind });\n continue;\n }\n\n current.score += score;\n if (item.timestamp > current.latestTs) {\n current.latestTs = item.timestamp;\n current.text = item.text;\n }\n }\n\n const sortedByKind = (kind: ReflectionMappedKind) => [...grouped.values()]\n .filter((row) => row.kind === kind)\n .sort((a, b) => {\n if (b.score !== a.score) return b.score - a.score;\n if (b.latestTs !== a.latestTs) return b.latestTs - a.latestTs;\n return a.text.localeCompare(b.text);\n })\n .slice(0, maxPerKind)\n .map((row) => row.text);\n\n return {\n userModel: sortedByKind(\"user-model\"),\n agentModel: sortedByKind(\"agent-model\"),\n lesson: sortedByKind(\"lesson\"),\n decision: sortedByKind(\"decision\"),\n };\n}\n\nfunction parseMappedKind(value: unknown): ReflectionMappedKind | null {\n if (value === \"user-model\" || value === \"agent-model\" || value === \"lesson\" || value === \"decision\") {\n return value;\n }\n return null;\n}\n\nexport function getReflectionDerivedDecayDefaults(): { midpointDays: number; k: number } {\n return {\n midpointDays: REFLECTION_DERIVED_DECAY_MIDPOINT_DAYS,\n k: REFLECTION_DERIVED_DECAY_K,\n };\n}\n\nexport function getReflectionInvariantDecayDefaults(): { midpointDays: number; k: number } {\n return {\n midpointDays: REFLECTION_INVARIANT_DECAY_MIDPOINT_DAYS,\n k: REFLECTION_INVARIANT_DECAY_K,\n };\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"resonance-state.d.ts","sourceRoot":"","sources":["../../src/resonance-state.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AA4CH;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAY7C;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAUxD"}
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/resonance-state.ts"],
4
- "sourcesContent": ["// SPDX-License-Identifier: MIT\n/**\n * Adaptive Resonance Threshold\n *\n * Maintains a sliding window of recent auto-recall top-1 cosine scores\n * to compute an adaptive resonance gate threshold (P25 of the window).\n * Persisted to ~/.openclaw/memory/resonance-state.json.\n */\n\nimport { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, dirname } from \"node:path\";\n\nconst STATE_PATH = join(homedir(), \".openclaw\", \"memory\", \"resonance-state.json\");\nconst WINDOW_SIZE = 100;\nconst COLD_START_MIN = 20;\nconst DEFAULT_THRESHOLD = 0.45;\nconst THRESHOLD_FLOOR = 0.30;\nconst THRESHOLD_CEILING = 0.60;\n\ninterface ResonanceStateData {\n scores: number[];\n}\n\nlet cached: ResonanceStateData | null = null;\n\nfunction loadState(): ResonanceStateData {\n if (cached) return cached;\n try {\n const raw = readFileSync(STATE_PATH, \"utf8\");\n const parsed = JSON.parse(raw);\n if (parsed && Array.isArray(parsed.scores)) {\n cached = { scores: parsed.scores.filter((s: unknown) => typeof s === \"number\" && Number.isFinite(s as number)).slice(-WINDOW_SIZE) };\n return cached;\n }\n } catch {\n // file doesn't exist or is corrupted \u2014 start fresh\n }\n cached = { scores: [] };\n return cached;\n}\n\nfunction saveState(state: ResonanceStateData): void {\n try {\n mkdirSync(dirname(STATE_PATH), { recursive: true });\n writeFileSync(STATE_PATH, JSON.stringify(state), \"utf8\");\n } catch {\n // best-effort persistence\n }\n}\n\n/**\n * Get the adaptive resonance threshold.\n * - Cold start (< 20 samples): returns default 0.45\n * - Otherwise: P25 of sliding window, clamped to [0.30, 0.60]\n */\nexport function getAdaptiveThreshold(): number {\n const state = loadState();\n if (state.scores.length < COLD_START_MIN) {\n return DEFAULT_THRESHOLD;\n }\n\n // Compute P25 (25th percentile)\n const sorted = [...state.scores].sort((a, b) => a - b);\n const idx = Math.floor(sorted.length * 0.25);\n const p25 = sorted[idx];\n\n return Math.min(THRESHOLD_CEILING, Math.max(THRESHOLD_FLOOR, p25));\n}\n\n/**\n * Record a top-1 cosine score from an auto-recall probe.\n * Appends to the sliding window and persists.\n */\nexport function recordResonanceScore(score: number): void {\n if (!Number.isFinite(score)) return;\n const state = loadState();\n state.scores.push(score);\n // Trim to window size\n if (state.scores.length > WINDOW_SIZE) {\n state.scores = state.scores.slice(-WINDOW_SIZE);\n }\n cached = state;\n saveState(state);\n}\n"],
5
- "mappings": "AASA,SAAS,cAAc,eAAe,iBAAiB;AACvD,SAAS,eAAe;AACxB,SAAS,MAAM,eAAe;AAE9B,MAAM,aAAa,KAAK,QAAQ,GAAG,aAAa,UAAU,sBAAsB;AAChF,MAAM,cAAc;AACpB,MAAM,iBAAiB;AACvB,MAAM,oBAAoB;AAC1B,MAAM,kBAAkB;AACxB,MAAM,oBAAoB;AAM1B,IAAI,SAAoC;AAExC,SAAS,YAAgC;AACvC,MAAI,OAAQ,QAAO;AACnB,MAAI;AACF,UAAM,MAAM,aAAa,YAAY,MAAM;AAC3C,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,QAAI,UAAU,MAAM,QAAQ,OAAO,MAAM,GAAG;AAC1C,eAAS,EAAE,QAAQ,OAAO,OAAO,OAAO,CAAC,MAAe,OAAO,MAAM,YAAY,OAAO,SAAS,CAAW,CAAC,EAAE,MAAM,CAAC,WAAW,EAAE;AACnI,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AACA,WAAS,EAAE,QAAQ,CAAC,EAAE;AACtB,SAAO;AACT;AAEA,SAAS,UAAU,OAAiC;AAClD,MAAI;AACF,cAAU,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAClD,kBAAc,YAAY,KAAK,UAAU,KAAK,GAAG,MAAM;AAAA,EACzD,QAAQ;AAAA,EAER;AACF;AAOO,SAAS,uBAA+B;AAC7C,QAAM,QAAQ,UAAU;AACxB,MAAI,MAAM,OAAO,SAAS,gBAAgB;AACxC,WAAO;AAAA,EACT;AAGA,QAAM,SAAS,CAAC,GAAG,MAAM,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACrD,QAAM,MAAM,KAAK,MAAM,OAAO,SAAS,IAAI;AAC3C,QAAM,MAAM,OAAO,GAAG;AAEtB,SAAO,KAAK,IAAI,mBAAmB,KAAK,IAAI,iBAAiB,GAAG,CAAC;AACnE;AAMO,SAAS,qBAAqB,OAAqB;AACxD,MAAI,CAAC,OAAO,SAAS,KAAK,EAAG;AAC7B,QAAM,QAAQ,UAAU;AACxB,QAAM,OAAO,KAAK,KAAK;AAEvB,MAAI,MAAM,OAAO,SAAS,aAAa;AACrC,UAAM,SAAS,MAAM,OAAO,MAAM,CAAC,WAAW;AAAA,EAChD;AACA,WAAS;AACT,YAAU,KAAK;AACjB;",
6
- "names": []
7
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"retriever.d.ts","sourceRoot":"","sources":["../../src/retriever.ts"],"names":[],"mappings":"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"}
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/retriever.ts"],
4
- "sourcesContent": ["// SPDX-License-Identifier: MIT\n/**\n * Hybrid Retrieval System\n * Combines vector search + BM25 full-text search with RRF fusion\n */\n\nimport type { MemoryEntry, MemoryStore, MemorySearchResult } from \"./store.js\";\nimport type { Embedder } from \"./embedder.js\";\nimport { filterNoise } from \"./noise-filter.js\";\nimport type { DecayEngine, DecayableMemory } from \"./decay-engine.js\";\nimport type { TierManager } from \"./tier-manager.js\";\nimport { toLifecycleMemory, getDecayableFromEntry } from \"./smart-metadata.js\";\nimport { getAdaptiveThreshold, recordResonanceScore } from \"./resonance-state.js\";\nimport { requirePro } from \"./license.js\";\nimport { log } from \"./logger.js\";\n\n// Pro: Access tracking & query tracking \u2014 graceful degradation without license\ntype AccessTracker = { bumpAccess: (id: string) => Promise<void> };\nlet _parseAccessMetadata: ((m: unknown) => { accessCount: number; lastAccessedAt: number }) | null = null;\nlet _computeEffectiveHalfLife: ((hl: number, ac: number, la: number, rf?: number, mx?: number) => number) | null = null;\n// TODO: type this with actual query-tracker signature\nlet _recordQuery: ((...args: unknown[]) => void) | null = null;\n\nif (requirePro(\"access-tracking\")) {\n import(\"./access-tracker.js\").then((mod) => {\n _parseAccessMetadata = mod.parseAccessMetadata;\n _computeEffectiveHalfLife = mod.computeEffectiveHalfLife;\n }).catch(() => {});\n}\nif (requirePro(\"query-tracking\")) {\n import(\"./query-tracker.js\").then((mod) => {\n _recordQuery = mod.recordQuery;\n }).catch(() => {});\n}\n\n// Fallbacks for Core mode (no access reinforcement)\nfunction parseAccessMetadata(m: unknown): { accessCount: number; lastAccessedAt: number } {\n if (_parseAccessMetadata) return _parseAccessMetadata(m);\n return { accessCount: 0, lastAccessedAt: 0 };\n}\nfunction computeEffectiveHalfLife(hl: number, _ac: number, _la: number, _rf?: number, _mx?: number): number {\n if (_computeEffectiveHalfLife) return _computeEffectiveHalfLife(hl, _ac, _la, _rf, _mx);\n return hl; // Core: use fixed half-life without reinforcement\n}\nfunction recordQuery(data: unknown): void {\n _recordQuery?.(data);\n}\nimport { appendFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n// ============================================================================\n// Graphiti Graph Search Integration (3rd retrieval path)\n// ============================================================================\n\n/** Lazy-read env at call time \u2014 openclaw.json env may inject after module load. */\nfunction getGraphitiConfig() {\n return {\n enabled: process.env.GRAPHITI_ENABLED === \"true\",\n baseUrl: process.env.GRAPHITI_BASE_URL || \"http://127.0.0.1:18799\",\n timeoutMs: 3000,\n };\n}\n\ninterface GraphitiFact {\n fact: string;\n source_node?: string;\n target_node?: string;\n from_node?: string;\n to_node?: string;\n created_at?: string;\n valid_at?: string | null;\n score?: number | null;\n degree?: number;\n source?: \"search\" | \"spread\";\n}\n\n/**\n * Query Graphiti /spread for graph-traversal results.\n * Returns synthetic MemorySearchResult entries. Fails silently (returns []).\n */\nasync function graphitiSpreadSearch(\n query: string,\n groupId: string = \"default\",\n searchLimit: number = 3,\n spreadLimit: number = 3,\n): Promise<Array<MemorySearchResult & { rank: number }>> {\n const cfg = getGraphitiConfig();\n if (!cfg.enabled) return [];\n\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), cfg.timeoutMs);\n const resp = await fetch(`${cfg.baseUrl}/spread`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n query,\n group_id: groupId,\n search_limit: searchLimit,\n spread_depth: 1,\n spread_limit: spreadLimit,\n }),\n signal: controller.signal,\n });\n clearTimeout(timeout);\n if (!resp.ok) return [];\n\n const facts: GraphitiFact[] = await resp.json();\n if (!Array.isArray(facts) || facts.length === 0) return [];\n\n const seen = new Set<string>();\n const results: Array<MemorySearchResult & { rank: number }> = [];\n\n for (let i = 0; i < facts.length; i++) {\n const f = facts[i];\n const factText = f.fact?.trim();\n if (!factText || factText.length < 5 || seen.has(factText)) continue;\n seen.add(factText);\n\n const nodes = [f.source_node, f.target_node, f.from_node, f.to_node]\n .filter(Boolean).join(\" \u2192 \");\n const text = nodes ? `[\u56FE\u8C31] ${factText} (${nodes})` : `[\u56FE\u8C31] ${factText}`;\n\n const baseScore = f.source === \"search\" ? 0.75 : 0.45;\n const degreeBoost = f.degree ? Math.min(0.15, Math.log1p(f.degree) * 0.02) : 0;\n\n results.push({\n entry: {\n id: `graphiti-${i}-${Date.now()}`,\n text,\n category: \"entity\" as const,\n importance: 0.8,\n timestamp: f.created_at ? new Date(f.created_at).getTime() : Date.now(),\n scope: \"global\",\n },\n score: Math.min(1.0, baseScore + degreeBoost),\n rank: i + 1,\n });\n }\n return results;\n } catch {\n return []; // Silent fallback\n }\n}\n\n// ============================================================================\n// Types & Configuration\n// ============================================================================\n\nexport interface RetrievalConfig {\n mode: \"hybrid\" | \"vector\";\n vectorWeight: number;\n bm25Weight: number;\n minScore: number;\n rerank: \"cross-encoder\" | \"lightweight\" | \"none\";\n candidatePoolSize: number;\n /** Recency boost half-life in days (default: 14). Set 0 to disable. */\n recencyHalfLifeDays: number;\n /** Max recency boost factor (default: 0.10) */\n recencyWeight: number;\n /** Filter noise from results (default: true) */\n filterNoise: boolean;\n /** Reranker API key (enables cross-encoder reranking) */\n rerankApiKey?: string;\n /** Reranker model (default: jina-reranker-v3) */\n rerankModel?: string;\n /** Reranker API endpoint (default: https://api.jina.ai/v1/rerank). */\n rerankEndpoint?: string;\n /** Reranker provider format. Determines request/response shape and auth header.\n * - \"jina\" (default): Authorization: Bearer, string[] documents, results[].relevance_score\n * - \"siliconflow\": same format as jina (alias, for clarity)\n * - \"voyage\": Authorization: Bearer, string[] documents, data[].relevance_score\n * - \"pinecone\": Api-Key header, {text}[] documents, data[].score */\n rerankProvider?: \"jina\" | \"siliconflow\" | \"voyage\" | \"pinecone\" | \"ollama\";\n /**\n * Length normalization: penalize long entries that dominate via sheer keyword\n * density. Formula: score *= 1 / (1 + log2(charLen / anchor)).\n * anchor = reference length (default: 500 chars). Entries shorter than anchor\n * get a slight boost; longer entries get penalized progressively.\n * Set 0 to disable. (default: 300)\n */\n lengthNormAnchor: number;\n /**\n * Hard cutoff after rerank: discard results below this score.\n * Applied after all scoring stages (rerank, recency, importance, length norm).\n * Higher = fewer but more relevant results. (default: 0.35)\n */\n hardMinScore: number;\n /**\n * Time decay half-life in days. Entries older than this lose score.\n * Different from recencyBoost (additive bonus for new entries):\n * this is a multiplicative penalty for old entries.\n * Formula: score *= 0.5 + 0.5 * exp(-ageDays / halfLife)\n * At halfLife days: ~0.68x. At 2*halfLife: ~0.59x. At 4*halfLife: ~0.52x.\n * Set 0 to disable. (default: 60)\n */\n timeDecayHalfLifeDays: number;\n /** Access reinforcement factor for time decay half-life extension.\n * Higher = stronger reinforcement. 0 to disable. (default: 0.5) */\n reinforcementFactor: number;\n /** Maximum half-life multiplier from access reinforcement.\n * Prevents frequently accessed memories from becoming immortal. (default: 3) */\n maxHalfLifeMultiplier: number;\n /** Enable multi-hop query routing: detected multi-hop queries skip Graphiti\n * spread and rely on LanceDB secondary retrieval instead. (default: true) */\n multiHopRouting: boolean;\n}\n\nexport interface RetrievalContext {\n query: string;\n limit: number;\n scopeFilter?: string[];\n category?: string;\n /** Retrieval source: \"manual\" for user-triggered, \"auto-recall\" for system-initiated, \"cli\" for CLI commands. */\n source?: \"manual\" | \"auto-recall\" | \"cli\";\n}\n\nexport interface RetrievalResult extends MemorySearchResult {\n sources: {\n vector?: { score: number; rank: number };\n bm25?: { score: number; rank: number };\n graphiti?: { score: number; rank: number };\n fused?: { score: number };\n reranked?: { score: number };\n };\n}\n\n// ============================================================================\n// Default Configuration\n// ============================================================================\n\nexport const DEFAULT_RETRIEVAL_CONFIG: RetrievalConfig = {\n mode: \"hybrid\",\n vectorWeight: 0.7,\n bm25Weight: 0.3,\n minScore: 0.3,\n rerank: \"cross-encoder\",\n candidatePoolSize: 20,\n recencyHalfLifeDays: 14,\n recencyWeight: 0.1,\n filterNoise: true,\n rerankModel: \"jina-reranker-v3\",\n rerankEndpoint: \"https://api.jina.ai/v1/rerank\",\n lengthNormAnchor: 500,\n hardMinScore: 0.35,\n timeDecayHalfLifeDays: 60,\n reinforcementFactor: 0.5,\n maxHalfLifeMultiplier: 3,\n multiHopRouting: true,\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: number): number {\n if (!Number.isFinite(value)) return Number.isFinite(fallback) ? fallback : 0;\n return Math.min(1, Math.max(0, value));\n}\n\nfunction clamp01WithFloor(value: number, floor: number): number {\n const safeFloor = clamp01(floor, 0);\n return Math.max(safeFloor, clamp01(value, safeFloor));\n}\n\n// ============================================================================\n// Rerank Provider Adapters\n// ============================================================================\n\ntype RerankProvider = \"jina\" | \"siliconflow\" | \"voyage\" | \"pinecone\" | \"ollama\";\n\ninterface RerankItem {\n index: number;\n score: number;\n}\n\n/** Build provider-specific request headers and body */\nfunction buildRerankRequest(\n provider: RerankProvider,\n apiKey: string,\n model: string,\n query: string,\n documents: string[],\n topN: number,\n): { headers: Record<string, string>; body: Record<string, unknown> } {\n switch (provider) {\n case \"pinecone\":\n return {\n headers: {\n \"Content-Type\": \"application/json\",\n \"Api-Key\": apiKey,\n \"X-Pinecone-API-Version\": \"2024-10\",\n },\n body: {\n model,\n query,\n documents: documents.map((text) => ({ text })),\n top_n: topN,\n rank_fields: [\"text\"],\n },\n };\n case \"voyage\":\n return {\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: {\n model,\n query,\n documents,\n // Voyage uses top_k (not top_n) to limit reranked outputs.\n top_k: topN,\n },\n };\n case \"ollama\":\n // Ollama rerank API: POST /api/rerank (available since Ollama 0.6+)\n // Models: jina-reranker-v1-turbo, bge-reranker-v2-m3, etc.\n // No API key needed for local Ollama\n return {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: {\n model,\n query,\n documents,\n top_n: topN,\n },\n };\n case \"siliconflow\":\n case \"jina\":\n default:\n return {\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: {\n model,\n query,\n documents,\n top_n: topN,\n },\n };\n }\n}\n\n/** Parse provider-specific response into unified format */\nfunction parseRerankResponse(\n provider: RerankProvider,\n data: Record<string, unknown>,\n): RerankItem[] | null {\n const parseItems = (\n items: unknown,\n scoreKeys: Array<\"score\" | \"relevance_score\">,\n ): RerankItem[] | null => {\n if (!Array.isArray(items)) return null;\n const parsed: RerankItem[] = [];\n for (const raw of items as Array<Record<string, unknown>>) {\n const index =\n typeof raw?.index === \"number\" ? raw.index : Number(raw?.index);\n if (!Number.isFinite(index)) continue;\n let score: number | null = null;\n for (const key of scoreKeys) {\n const value = raw?.[key];\n const n = typeof value === \"number\" ? value : Number(value);\n if (Number.isFinite(n)) {\n score = n;\n break;\n }\n }\n if (score === null) continue;\n parsed.push({ index, score });\n }\n return parsed.length > 0 ? parsed : null;\n };\n\n switch (provider) {\n case \"ollama\": {\n // Ollama: { results: [{ index, relevance_score }] }\n // Same format as Jina, but also check data[] for compatibility\n return (\n parseItems(data.results, [\"relevance_score\", \"score\"]) ??\n parseItems(data.data, [\"relevance_score\", \"score\"])\n );\n }\n case \"pinecone\": {\n // Pinecone: usually { data: [{ index, score, ... }] }\n // Also tolerate results[] with score/relevance_score for robustness.\n return (\n parseItems(data.data, [\"score\", \"relevance_score\"]) ??\n parseItems(data.results, [\"score\", \"relevance_score\"])\n );\n }\n case \"voyage\": {\n // Voyage: usually { data: [{ index, relevance_score }] }\n // Also tolerate results[] for compatibility across gateways.\n return (\n parseItems(data.data, [\"relevance_score\", \"score\"]) ??\n parseItems(data.results, [\"relevance_score\", \"score\"])\n );\n }\n case \"siliconflow\":\n case \"jina\":\n default: {\n // Jina / SiliconFlow: usually { results: [{ index, relevance_score }] }\n // Also tolerate data[] for compatibility across gateways.\n return (\n parseItems(data.results, [\"relevance_score\", \"score\"]) ??\n parseItems(data.data, [\"relevance_score\", \"score\"])\n );\n }\n }\n}\n\n// Cosine similarity for reranking fallback\nfunction cosineSimilarity(a: number[], b: number[]): number {\n if (a.length !== b.length) {\n throw new Error(\"Vector dimensions must match for cosine similarity\");\n }\n\n let dotProduct = 0;\n let normA = 0;\n let normB = 0;\n\n for (let i = 0; i < a.length; i++) {\n dotProduct += a[i] * b[i];\n normA += a[i] * a[i];\n normB += b[i] * b[i];\n }\n\n const norm = Math.sqrt(normA) * Math.sqrt(normB);\n return norm === 0 ? 0 : dotProduct / norm;\n}\n\n// ============================================================================\n// Memory Retriever\n// ============================================================================\n\nconst RETRIEVAL_LOG_PATH = join(homedir(), \".openclaw\", \"memory\", \"retrieval-log.jsonl\");\n\nexport class MemoryRetriever {\n private accessTracker: AccessTracker | null = null;\n private tierManager: TierManager | null = null;\n\n constructor(\n private store: MemoryStore,\n private embedder: Embedder,\n private config: RetrievalConfig = DEFAULT_RETRIEVAL_CONFIG,\n private decayEngine: DecayEngine | null = null,\n ) { }\n\n setAccessTracker(tracker: AccessTracker): void {\n this.accessTracker = tracker;\n }\n\n /**\n * Resonance check: fast vector probe to see if the query \"resonates\"\n * with any high-salience memories. Returns true if at least one memory\n * has cosine similarity above threshold. This mimics human associative\n * memory \u2014 most inputs don't trigger recall, only resonant ones do.\n */\n private async resonanceCheck(\n query: string,\n scopeFilter?: string[],\n ): Promise<{ resonates: boolean; topScore: number }> {\n try {\n const queryVector = await this.embedder.embedQuery(query);\n const threshold = getAdaptiveThreshold();\n const probeResults = await this.store.vectorSearch(\n queryVector,\n 3,\n threshold,\n scopeFilter,\n );\n if (probeResults.length === 0) return { resonates: false, topScore: 0 };\n\n const topScore = Math.max(...probeResults.map(r => r.score));\n\n // Record top score for adaptive threshold sliding window\n recordResonanceScore(topScore);\n\n // At least one result resonates \u2014 check if it has meaningful salience\n // (not just a random match with a low-importance peripheral memory)\n for (const r of probeResults) {\n const importance = r.entry.importance ?? 0.5;\n const similarity = r.score;\n // Resonance = strong similarity OR moderate similarity + high importance\n if (similarity >= 0.55 || (similarity >= threshold && importance >= 0.7)) {\n return { resonates: true, topScore };\n }\n }\n return { resonates: false, topScore };\n } catch {\n // If resonance check fails, allow recall (fail-open)\n return { resonates: true, topScore: 0 };\n }\n }\n\n /**\n * Strip metadata blocks from auto-recall queries.\n * OpenClaw core may pass the full message including Conversation info,\n * Replied message, and Sender metadata JSON blocks. We only want the\n * actual user text for semantic search.\n */\n private cleanAutoRecallQuery(raw: string): string {\n // Remove ```json ... ``` code blocks (metadata envelopes)\n let cleaned = raw.replace(/```json[\\s\\S]*?```/g, \"\");\n // Remove known metadata headers\n cleaned = cleaned.replace(/Conversation info \\(untrusted metadata\\):/g, \"\");\n cleaned = cleaned.replace(/Sender \\(untrusted metadata\\):/g, \"\");\n cleaned = cleaned.replace(/Replied message \\(untrusted, for context\\):/g, \"\");\n // Remove [Queued messages ...] headers\n cleaned = cleaned.replace(/\\[Queued messages[^\\]]*\\]/g, \"\");\n cleaned = cleaned.replace(/---\\s*\\nQueued #\\d+/g, \"\");\n // Collapse whitespace\n cleaned = cleaned.replace(/\\n{3,}/g, \"\\n\").trim();\n // If nothing left after cleaning, return original (safety)\n return cleaned.length > 2 ? cleaned : raw;\n }\n\n /**\n * Expand date expressions in query to multiple formats for BM25 matching.\n * \"3\u670817\u65E5\" \u2192 \"3\u670817\u65E5 3/17 03-17 2026-03-17\"\n * \"2026\u5E743\u670817\u65E5\" \u2192 \"2026\u5E743\u670817\u65E5 3/17 2026-03-17 03-17\"\n * \"\u6628\u5929/\u524D\u5929/\u4E0A\u5468\" \u2192 resolved to absolute dates\n */\n private expandDateFormats(query: string): string {\n const now = new Date();\n const year = now.getFullYear();\n let expanded = query;\n\n // Pattern: X\u6708Y\u65E5 or X\u6708Y\u53F7\n expanded = expanded.replace(/(\\d{1,2})\u6708(\\d{1,2})[\u65E5\u53F7]/g, (match, m, d) => {\n const mm = String(m).padStart(2, \"0\");\n const dd = String(d).padStart(2, \"0\");\n return `${match} ${m}/${d} ${year}-${mm}-${dd} ${mm}-${dd}`;\n });\n\n // Pattern: YYYY\u5E74X\u6708Y\u65E5\n expanded = expanded.replace(/(\\d{4})\u5E74(\\d{1,2})\u6708(\\d{1,2})[\u65E5\u53F7]/g, (match, y, m, d) => {\n const mm = String(m).padStart(2, \"0\");\n const dd = String(d).padStart(2, \"0\");\n return `${match} ${m}/${d} ${y}-${mm}-${dd} ${mm}-${dd}`;\n });\n\n // Pattern: X.Y or X/Y (might be dates like 3/17)\n // Don't expand \u2014 these are already BM25-friendly\n\n // Relative dates\n const relMap: Record<string, number> = {\n \"\u4ECA\u5929\": 0, \"\u6628\u5929\": -1, \"\u524D\u5929\": -2, \"\u5927\u524D\u5929\": -3,\n };\n for (const [word, offset] of Object.entries(relMap)) {\n if (expanded.includes(word)) {\n const d = new Date(now.getTime() + offset * 86400000);\n const iso = d.toISOString().slice(0, 10);\n const m = d.getMonth() + 1;\n const day = d.getDate();\n expanded = expanded.replace(word, `${word} ${iso} ${m}/${day} ${m}\u6708${day}\u65E5`);\n }\n }\n\n return expanded;\n }\n\n async retrieve(context: RetrievalContext): Promise<RetrievalResult[]> {\n let { query, limit, scopeFilter, category, source } = context;\n // Clean metadata pollution from auto-recall queries\n if (source === \"auto-recall\") {\n query = this.cleanAutoRecallQuery(query);\n }\n const safeLimit = clampInt(limit, 1, 20);\n const t0 = performance.now();\n\n // \u2500\u2500 \u5171\u632F\u95E8\u63A7\uFF1Aauto-recall \u65F6\u5148\u505A\u5FEB\u901F\u5171\u632F\u68C0\u6D4B \u2500\u2500\n let resonanceTriggered = false;\n let resonanceTopScore = 0;\n if (source === \"auto-recall\") {\n const { resonates, topScore: probeTopScore } = await this.resonanceCheck(query, scopeFilter);\n resonanceTriggered = resonates;\n resonanceTopScore = probeTopScore;\n if (!resonates) {\n // Fire-and-forget tracking for gated-out queries\n const trackEntry = JSON.stringify({\n ts: new Date().toISOString(),\n query: query.substring(0, 200),\n source: source || \"manual\",\n queryType: \"gated-out\",\n resonanceScore: resonanceTopScore,\n resonanceTriggered: false,\n lancedbCount: 0,\n graphitiCount: 0,\n rerankCount: 0,\n finalCount: 0,\n totalLatencyMs: Math.round(performance.now() - t0),\n lancedbLatencyMs: 0,\n graphitiLatencyMs: 0,\n rerankLatencyMs: 0,\n }) + \"\\n\";\n appendFile(RETRIEVAL_LOG_PATH, trackEntry).catch(() => {});\n recordQuery({\n timestamp: new Date().toISOString(),\n query: query.substring(0, 200),\n source: (source === \"auto-recall\" ? \"auto\" : source || \"manual\") as \"auto\" | \"manual\" | \"cli\",\n hitCount: 0,\n topScore: resonanceTopScore,\n latency_ms: Math.round(performance.now() - t0),\n queryType: \"gated-out\",\n resonancePass: false,\n });\n return []; // \u65E0\u5171\u632F \u2192 \u4E0D\u6CE8\u5165\u8BB0\u5FC6\n }\n }\n\n // \u2500\u2500 Multi-hop \u68C0\u6D4B \u2500\u2500\n const isMultiHop = this.config.multiHopRouting && this.isMultiHopQuery(query);\n\n // \u2500\u2500 \u5E76\u53D1\u67E5\u8BE2\uFF1ALanceDB + Graphiti \u2500\u2500\n const tLance0 = performance.now();\n const lanceDbPromise = (async () => {\n if (this.config.mode === \"vector\" || !this.store.hasFtsSupport) {\n return this.vectorOnlyRetrieval(query, safeLimit, scopeFilter, category);\n } else {\n return this.hybridRetrieval(query, safeLimit, scopeFilter, category);\n }\n })();\n\n const tGraphiti0 = performance.now();\n const graphitiPromise = (async (): Promise<RetrievalResult[]> => {\n if (process.env.GRAPHITI_ENABLED !== \"true\") return [];\n try {\n const graphitiBase = process.env.GRAPHITI_BASE_URL || \"http://127.0.0.1:18799\";\n const scope = scopeFilter?.[0] || \"default\";\n const groupId = scope.startsWith(\"agent:\") ? scope.split(\":\")[1] || \"default\" : \"default\";\n\n // Multi-hop queries skip spread (spread follows single-entity neighborhoods)\n const useSpread = source === \"auto-recall\" && !isMultiHop;\n const endpoint = useSpread ? \"/spread\" : \"/search\";\n const body = useSpread\n ? { query, group_id: groupId, search_limit: 3, spread_depth: 1, spread_limit: 3 }\n : { query, group_id: groupId, limit: Math.min(safeLimit, 5) };\n\n const resp = await fetch(`${graphitiBase}${endpoint}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(5000),\n });\n if (!resp.ok) return [];\n\n const facts = (await resp.json()) as Array<{\n fact: string; valid_at?: string; expired_at?: string; created_at?: string;\n degree?: number; source?: string;\n }>;\n return facts\n .filter(f => f.fact && !f.expired_at)\n .map((f, i) => {\n const isSpread = f.source === \"spread\";\n const degreeBoost = f.degree ? Math.min(0.15, Math.log1p(f.degree) * 0.03) : 0;\n const baseScore = isSpread ? 0.45 : 0.65;\n return {\n entry: {\n id: `graphiti-${Date.now()}-${i}`,\n text: f.fact,\n vector: [],\n category: \"fact\" as const,\n scope: scope,\n importance: 0.7,\n timestamp: f.valid_at ? new Date(f.valid_at).getTime() : Date.now(),\n metadata: JSON.stringify({ source: isSpread ? \"graphiti-spread\" : \"graphiti\", valid_at: f.valid_at, degree: f.degree }),\n },\n score: baseScore + (0.01 * (facts.length - i)) + degreeBoost,\n sources: { graphiti: { rank: i + 1 } },\n } as RetrievalResult;\n });\n } catch {\n return [];\n }\n })();\n\n const [lanceResults, graphitiResults] = await Promise.all([lanceDbPromise, graphitiPromise]);\n const tLanceMs = Math.round(performance.now() - tLance0);\n const tGraphitiMs = Math.round(performance.now() - tGraphiti0);\n\n // Merge: LanceDB results first, append non-duplicate Graphiti facts\n const lanceTexts = new Set(lanceResults.map(r => r.entry.text.slice(0, 80)));\n const uniqueGraphiti = graphitiResults.filter(\n r => !lanceTexts.has(r.entry.text.slice(0, 80))\n );\n\n // \u2500\u2500 \u8DE8\u6E90\u7EDF\u4E00 Rerank\uFF08\u6240\u6709\u7ED3\u679C\u90FD\u8FC7 reranker\uFF09\u2500\u2500\n let merged: RetrievalResult[];\n let rerankCount = 0;\n const tRerank0 = performance.now();\n const combined = [...lanceResults, ...uniqueGraphiti];\n if (this.config.rerank !== \"none\" && this.config.rerankApiKey && combined.length > 0) {\n const queryVector = await this.embedder.embedQuery(query);\n merged = await this.rerankResults(query, queryVector, combined);\n rerankCount = merged.length;\n merged = merged.slice(0, safeLimit);\n } else {\n merged = combined.slice(0, safeLimit);\n }\n const tRerankMs = Math.round(performance.now() - tRerank0);\n\n // Record access for reinforcement (manual recall only)\n if (this.accessTracker && source === \"manual\" && merged.length > 0) {\n this.accessTracker.recordAccess(\n merged.filter(r => !r.entry.id.startsWith(\"graphiti-\")).map(r => r.entry.id)\n );\n }\n\n // \u2500\u2500 Fire-and-forget tracking log \u2500\u2500\n const topScore = merged.length > 0 ? Math.max(...merged.map(r => r.score)) : 0;\n const trackEntry = JSON.stringify({\n ts: new Date().toISOString(),\n query: query.substring(0, 200),\n source: source || \"manual\",\n queryType: isMultiHop ? \"multi-hop\" : \"single\",\n resonanceScore: topScore,\n resonanceTriggered,\n lancedbCount: lanceResults.length,\n graphitiCount: graphitiResults.length,\n rerankCount,\n finalCount: merged.length,\n totalLatencyMs: Math.round(performance.now() - t0),\n lancedbLatencyMs: tLanceMs,\n graphitiLatencyMs: tGraphitiMs,\n rerankLatencyMs: tRerankMs,\n }) + \"\\n\";\n appendFile(RETRIEVAL_LOG_PATH, trackEntry).catch(() => {});\n recordQuery({\n timestamp: new Date().toISOString(),\n query: query.substring(0, 200),\n source: (source === \"auto-recall\" ? \"auto\" : source || \"manual\") as \"auto\" | \"manual\" | \"cli\",\n hitCount: merged.length,\n topScore,\n latency_ms: Math.round(performance.now() - t0),\n queryType: isMultiHop ? \"multi-hop\" : \"single\",\n resonancePass: true,\n });\n\n return merged;\n }\n\n private async vectorOnlyRetrieval(\n query: string,\n limit: number,\n scopeFilter?: string[],\n category?: string,\n ): Promise<RetrievalResult[]> {\n const queryVector = await this.embedder.embedQuery(query);\n const results = await this.store.vectorSearch(\n queryVector,\n limit,\n this.config.minScore,\n scopeFilter,\n );\n\n // Filter by category if specified\n const filtered = category\n ? results.filter((r) => r.entry.category === category)\n : results;\n\n const mapped = filtered.map(\n (result, index) =>\n ({\n ...result,\n sources: {\n vector: { score: result.score, rank: index + 1 },\n },\n }) as RetrievalResult,\n );\n\n const weighted = this.decayEngine ? mapped : this.applyImportanceWeight(this.applyRecencyBoost(mapped));\n const lengthNormalized = this.applyLengthNormalization(weighted);\n const hardFiltered = lengthNormalized.filter(r => r.score >= this.config.hardMinScore);\n const lifecycleRanked = this.decayEngine\n ? this.applyDecayBoost(hardFiltered)\n : this.applyTimeDecay(hardFiltered);\n const denoised = this.config.filterNoise\n ? filterNoise(lifecycleRanked, r => r.entry.text)\n : lifecycleRanked;\n\n // MMR deduplication: avoid top-k filled with near-identical memories\n const deduplicated = this.applyMMRDiversity(denoised);\n\n return deduplicated.slice(0, limit);\n }\n\n private async hybridRetrieval(\n query: string,\n limit: number,\n scopeFilter?: string[],\n category?: string,\n ): Promise<RetrievalResult[]> {\n const candidatePoolSize = Math.max(\n this.config.candidatePoolSize,\n limit * 2,\n );\n\n // Compute query embedding once, reuse for vector search + reranking\n const queryVector = await this.embedder.embedQuery(query);\n\n // Run vector, BM25, and Graphiti searches in parallel (3-way)\n const [vectorResults, bm25Results, graphitiResults] = await Promise.all([\n this.runVectorSearch(\n queryVector,\n candidatePoolSize,\n scopeFilter,\n category,\n ),\n this.runBM25Search(query, candidatePoolSize, scopeFilter, category),\n graphitiSpreadSearch(query, \"default\", 3, 3),\n ]);\n\n // Fuse results using RRF (async: validates BM25-only entries exist in store)\n // Graphiti results merged as 3rd signal\n const fusedResults = await this.fuseResults(vectorResults, bm25Results, graphitiResults);\n\n // Apply minimum score threshold\n const filtered = fusedResults.filter(\n (r) => r.score >= this.config.minScore,\n );\n\n // Rerank if enabled\n const reranked =\n this.config.rerank !== \"none\"\n ? await this.rerankResults(\n query,\n queryVector,\n filtered.slice(0, limit * 2),\n )\n : filtered;\n\n const temporallyRanked = this.decayEngine\n ? reranked\n : this.applyImportanceWeight(this.applyRecencyBoost(reranked));\n\n // Apply length normalization (penalize long entries dominating via keyword density)\n const lengthNormalized = this.applyLengthNormalization(temporallyRanked);\n\n // Hard minimum score cutoff should be based on semantic / lexical relevance.\n // Lifecycle decay and time-decay are used for re-ranking, not for dropping\n // otherwise relevant fresh memories.\n const hardFiltered = lengthNormalized.filter(r => r.score >= this.config.hardMinScore);\n\n // Apply lifecycle-aware decay or legacy time decay after thresholding\n const lifecycleRanked = this.decayEngine\n ? this.applyDecayBoost(hardFiltered)\n : this.applyTimeDecay(hardFiltered);\n\n // Filter noise\n const denoised = this.config.filterNoise\n ? filterNoise(lifecycleRanked, r => r.entry.text)\n : lifecycleRanked;\n\n // MMR deduplication: avoid top-k filled with near-identical memories\n const deduplicated = this.applyMMRDiversity(denoised);\n\n return deduplicated.slice(0, limit);\n }\n\n private async runVectorSearch(\n queryVector: number[],\n limit: number,\n scopeFilter?: string[],\n category?: string,\n ): Promise<Array<MemorySearchResult & { rank: number }>> {\n const results = await this.store.vectorSearch(\n queryVector,\n limit,\n 0.1,\n scopeFilter,\n );\n\n // Filter by category if specified\n const filtered = category\n ? results.filter((r) => r.entry.category === category)\n : results;\n\n return filtered.map((result, index) => ({\n ...result,\n rank: index + 1,\n }));\n }\n\n private async runBM25Search(\n query: string,\n limit: number,\n scopeFilter?: string[],\n category?: string,\n ): Promise<Array<MemorySearchResult & { rank: number }>> {\n // Expand date formats for better BM25 matching\n const expandedQuery = this.expandDateFormats(query);\n const results = await this.store.bm25Search(expandedQuery, limit, scopeFilter);\n\n // Filter by category if specified\n const filtered = category\n ? results.filter((r) => r.entry.category === category)\n : results;\n\n return filtered.map((result, index) => ({\n ...result,\n rank: index + 1,\n }));\n }\n\n private async fuseResults(\n vectorResults: Array<MemorySearchResult & { rank: number }>,\n bm25Results: Array<MemorySearchResult & { rank: number }>,\n graphitiResults: Array<MemorySearchResult & { rank: number }> = [],\n ): Promise<RetrievalResult[]> {\n // Create maps for quick lookup\n const vectorMap = new Map<string, MemorySearchResult & { rank: number }>();\n const bm25Map = new Map<string, MemorySearchResult & { rank: number }>();\n\n vectorResults.forEach((result) => {\n vectorMap.set(result.entry.id, result);\n });\n\n bm25Results.forEach((result) => {\n bm25Map.set(result.entry.id, result);\n });\n\n // Get all unique document IDs\n const allIds = new Set([...vectorMap.keys(), ...bm25Map.keys()]);\n\n // Calculate RRF scores\n const fusedResults: RetrievalResult[] = [];\n\n for (const id of allIds) {\n const vectorResult = vectorMap.get(id);\n const bm25Result = bm25Map.get(id);\n\n // FIX(#15): BM25-only results may be \"ghost\" entries whose vector data was\n // deleted but whose FTS index entry lingers until the next index rebuild.\n // Validate that the entry actually exists in the store before including it.\n if (!vectorResult && bm25Result) {\n try {\n const exists = await this.store.hasId(id);\n if (!exists) continue; // Skip ghost entry\n } catch {\n // If hasId fails, keep the result (fail-open)\n }\n }\n\n // Use the result with more complete data (prefer vector result if both exist)\n const baseResult = vectorResult || bm25Result!;\n\n // Use vector similarity as the base score.\n // BM25 hit acts as a bonus (keyword match confirms relevance).\n const vectorScore = vectorResult ? vectorResult.score : 0;\n const bm25Score = bm25Result ? bm25Result.score : 0;\n // Weighted fusion: vectorWeight/bm25Weight directly control score blending.\n // BM25 high-score floor (>= 0.75) preserves exact keyword matches\n // (e.g. API keys, ticket numbers) that may have low vector similarity.\n const weightedFusion = (vectorScore * this.config.vectorWeight)\n + (bm25Score * this.config.bm25Weight);\n const fusedScore = vectorResult\n ? clamp01(\n Math.max(\n weightedFusion,\n bm25Score >= 0.75 ? bm25Score * 0.92 : 0,\n ),\n 0.1,\n )\n : clamp01(bm25Result!.score, 0.1);\n\n fusedResults.push({\n entry: baseResult.entry,\n score: fusedScore,\n sources: {\n vector: vectorResult\n ? { score: vectorResult.score, rank: vectorResult.rank }\n : undefined,\n bm25: bm25Result\n ? { score: bm25Result.score, rank: bm25Result.rank }\n : undefined,\n fused: { score: fusedScore },\n },\n });\n }\n\n // Inject Graphiti graph traversal results as 3rd signal.\n // Synthetic entries (not in LanceDB) \u2014 scored slightly lower to avoid dominating,\n // but provide coverage for relational queries (e.g. \"Alice's clients\", \"who did Bob meet?\").\n for (const gr of graphitiResults) {\n fusedResults.push({\n entry: gr.entry,\n score: gr.score * 0.85,\n sources: {\n graphiti: { score: gr.score, rank: gr.rank },\n fused: { score: gr.score * 0.85 },\n },\n });\n }\n\n // Sort by fused score descending\n return fusedResults.sort((a, b) => b.score - a.score);\n }\n\n /**\n * Rerank results using cross-encoder API (Jina, Pinecone, or compatible).\n * Falls back to cosine similarity if API is unavailable or fails.\n */\n private async rerankResults(\n query: string,\n queryVector: number[],\n results: RetrievalResult[],\n ): Promise<RetrievalResult[]> {\n if (results.length === 0) {\n return results;\n }\n\n // Try cross-encoder rerank via configured provider API\n log.warn(`[rerank-debug] rerank=${this.config.rerank}, hasKey=${!!this.config.rerankApiKey}, keyPrefix=${String(this.config.rerankApiKey || '').substring(0, 8)}, provider=${this.config.rerankProvider}, model=${this.config.rerankModel}`);\n const isLocalRerank = this.config.rerankProvider === \"ollama\";\n if (this.config.rerank === \"cross-encoder\" && (this.config.rerankApiKey || isLocalRerank)) {\n try {\n const provider = this.config.rerankProvider || \"jina\";\n const model = this.config.rerankModel || (isLocalRerank ? \"bge-reranker-v2-m3\" : \"jina-reranker-v3\");\n const endpoint =\n this.config.rerankEndpoint || (isLocalRerank ? \"http://127.0.0.1:11434/api/rerank\" : \"https://api.jina.ai/v1/rerank\");\n const documents = results.map((r) => r.entry.text);\n\n // Build provider-specific request\n const { headers, body } = buildRerankRequest(\n provider,\n this.config.rerankApiKey,\n model,\n query,\n documents,\n results.length,\n );\n\n // Timeout: 5 seconds to prevent stalling retrieval pipeline\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 5000);\n\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n clearTimeout(timeout);\n\n if (response.ok) {\n const data = (await response.json()) as Record<string, unknown>;\n\n // Parse provider-specific response into unified format\n const parsed = parseRerankResponse(provider, data);\n\n if (!parsed) {\n log.warn(\n \"Rerank API: invalid response shape, falling back to cosine\",\n );\n } else {\n // Build a Set of returned indices to identify unreturned candidates\n const returnedIndices = new Set(parsed.map((r) => r.index));\n\n const reranked = parsed\n .filter((item) => item.index >= 0 && item.index < results.length)\n .map((item) => {\n const original = results[item.index];\n const floor = this.getRerankPreservationFloor(original, false);\n // Blend: 60% cross-encoder score + 40% original fused score\n const blendedScore = clamp01WithFloor(\n item.score * 0.6 + original.score * 0.4,\n floor,\n );\n return {\n ...original,\n score: blendedScore,\n sources: {\n ...original.sources,\n reranked: { score: item.score },\n },\n };\n });\n\n // Keep unreturned candidates with their original scores (slightly penalized)\n const unreturned = results\n .filter((_, idx) => !returnedIndices.has(idx))\n .map(r => ({\n ...r,\n score: clamp01WithFloor(\n r.score * 0.8,\n this.getRerankPreservationFloor(r, true),\n ),\n }));\n\n return [...reranked, ...unreturned].sort(\n (a, b) => b.score - a.score,\n );\n }\n } else {\n const errText = await response.text().catch(() => \"\");\n log.warn(\n `Rerank API returned ${response.status}: ${errText.slice(0, 200)}, falling back to cosine`,\n );\n }\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n log.warn(\"Rerank API timed out (5s), falling back to cosine\");\n } else {\n log.warn(\"Rerank API failed, falling back to cosine:\", error);\n }\n }\n }\n\n // Fallback: lightweight cosine similarity rerank\n try {\n const reranked = results.map((result) => {\n const cosineScore = cosineSimilarity(queryVector, result.entry.vector);\n const combinedScore = result.score * 0.7 + cosineScore * 0.3;\n\n return {\n ...result,\n score: clamp01(combinedScore, result.score),\n sources: {\n ...result.sources,\n reranked: { score: cosineScore },\n },\n };\n });\n\n return reranked.sort((a, b) => b.score - a.score);\n } catch (error) {\n log.warn(\"Reranking failed, returning original results:\", error);\n return results;\n }\n }\n\n private getRerankPreservationFloor(result: RetrievalResult, unreturned: boolean): number {\n const bm25Score = result.sources.bm25?.score ?? 0;\n\n // Exact lexical hits (IDs, env vars, ticket numbers) should not disappear\n // just because a reranker under-scores symbolic or mixed-language queries.\n if (bm25Score >= 0.75) {\n return result.score * (unreturned ? 1.0 : 0.95);\n }\n if (bm25Score >= 0.6) {\n return result.score * (unreturned ? 0.95 : 0.9);\n }\n return result.score * (unreturned ? 0.8 : 0.5);\n }\n\n /**\n * Apply recency boost: newer memories get a small score bonus.\n * This ensures corrections/updates naturally outrank older entries\n * when semantic similarity is close.\n * Formula: boost = exp(-ageDays / halfLife) * weight\n */\n private applyRecencyBoost(results: RetrievalResult[]): RetrievalResult[] {\n const { recencyHalfLifeDays, recencyWeight } = this.config;\n if (!recencyHalfLifeDays || recencyHalfLifeDays <= 0 || !recencyWeight) {\n return results;\n }\n\n const now = Date.now();\n const boosted = results.map((r) => {\n const ts =\n r.entry.timestamp && r.entry.timestamp > 0 ? r.entry.timestamp : now;\n const ageDays = (now - ts) / 86_400_000;\n const boost = Math.exp(-ageDays / recencyHalfLifeDays) * recencyWeight;\n return {\n ...r,\n score: clamp01(r.score + boost, r.score),\n };\n });\n\n return boosted.sort((a, b) => b.score - a.score);\n }\n\n /**\n * Apply importance weighting: memories with higher importance get a score boost.\n * This ensures critical memories (importance=1.0) outrank casual ones (importance=0.5)\n * when semantic similarity is close.\n * Formula: score *= (baseWeight + (1 - baseWeight) * importance)\n * With baseWeight=0.7: importance=1.0 \u2192 \u00D71.0, importance=0.5 \u2192 \u00D70.85, importance=0.0 \u2192 \u00D70.7\n */\n private applyImportanceWeight(results: RetrievalResult[]): RetrievalResult[] {\n const baseWeight = 0.7;\n const weighted = results.map((r) => {\n const importance = r.entry.importance ?? 0.7;\n const factor = baseWeight + (1 - baseWeight) * importance;\n return {\n ...r,\n score: clamp01(r.score * factor, r.score * baseWeight),\n };\n });\n return weighted.sort((a, b) => b.score - a.score);\n }\n\n private applyDecayBoost(results: RetrievalResult[]): RetrievalResult[] {\n if (!this.decayEngine || results.length === 0) return results;\n\n const scored = results.map((result) => ({\n memory: toLifecycleMemory(result.entry.id, result.entry),\n score: result.score,\n }));\n\n this.decayEngine.applySearchBoost(scored);\n\n const reranked = results.map((result, index) => ({\n ...result,\n score: clamp01(scored[index].score, result.score * 0.3),\n }));\n\n return reranked.sort((a, b) => b.score - a.score);\n }\n\n /**\n * Detect multi-hop queries that involve multiple entities or relationships.\n * Multi-hop queries benefit from LanceDB secondary retrieval rather than\n * Graphiti spread (which follows single-entity neighborhoods).\n */\n private isMultiHopQuery(query: string): boolean {\n // Count distinct capitalized words (potential entity names, >= 2 chars)\n const capitalizedWords = new Set(\n (query.match(/\\b[A-Z\\u4e00-\\u9fff][a-zA-Z\\u4e00-\\u9fff]{1,}/g) || [])\n );\n if (capitalizedWords.size >= 2) return true;\n\n // Relationship / comparison patterns\n const relationPatterns = [\n /\u548C.{1,20}\u7684\u5173\u7CFB/,\n /compared\\s+to/i,\n /difference\\s+between/i,\n /\u4E3A\u4EC0\u4E48/,\n /how\\s+does\\s+.{1,30}\\s+relate\\s+to/i,\n /between\\s+.{1,30}\\s+and\\s+/i,\n /\u76F8\u6BD4/,\n /\u533A\u522B/,\n /\u4E4B\u95F4/,\n ];\n for (const pat of relationPatterns) {\n if (pat.test(query)) return true;\n }\n\n // Long query with question mark\n if (query.length > 100 && /[?\uFF1F]/.test(query)) return true;\n\n return false;\n }\n\n /**\n * via sheer keyword density and broad semantic coverage.\n * Short, focused entries (< anchor) get a slight boost.\n * Long, sprawling entries (> anchor) get penalized.\n * Formula: score *= 1 / (1 + log2(charLen / anchor))\n */\n private applyLengthNormalization(\n results: RetrievalResult[],\n ): RetrievalResult[] {\n const anchor = this.config.lengthNormAnchor;\n if (!anchor || anchor <= 0) return results;\n\n const normalized = results.map((r) => {\n const charLen = r.entry.text.length;\n const ratio = charLen / anchor;\n // No penalty for entries at or below anchor length.\n // Gentle logarithmic decay for longer entries:\n // anchor (500) \u2192 1.0, 800 \u2192 0.75, 1000 \u2192 0.67, 1500 \u2192 0.56, 2000 \u2192 0.50\n // This prevents long, keyword-rich entries from dominating top-k\n // while keeping their scores reasonable.\n const logRatio = Math.log2(Math.max(ratio, 1)); // no boost for short entries\n const factor = 1 / (1 + 0.5 * logRatio);\n return {\n ...r,\n score: clamp01(r.score * factor, r.score * 0.3),\n };\n });\n\n return normalized.sort((a, b) => b.score - a.score);\n }\n\n /**\n * Time decay: multiplicative penalty for old entries.\n * Unlike recencyBoost (additive bonus for new entries), this actively\n * penalizes stale information so recent knowledge wins ties.\n * Formula: score *= 0.5 + 0.5 * exp(-ageDays / halfLife)\n * At 0 days: 1.0x (no penalty)\n * At halfLife: ~0.68x\n * At 2*halfLife: ~0.59x\n * Floor at 0.5x (never penalize more than half)\n */\n private applyTimeDecay(results: RetrievalResult[]): RetrievalResult[] {\n const halfLife = this.config.timeDecayHalfLifeDays;\n if (!halfLife || halfLife <= 0) return results;\n\n const now = Date.now();\n const decayed = results.map((r) => {\n const ts =\n r.entry.timestamp && r.entry.timestamp > 0 ? r.entry.timestamp : now;\n const ageDays = (now - ts) / 86_400_000;\n\n // Access reinforcement: frequently recalled memories decay slower\n const { accessCount, lastAccessedAt } = parseAccessMetadata(\n r.entry.metadata,\n );\n const effectiveHL = computeEffectiveHalfLife(\n halfLife,\n accessCount,\n lastAccessedAt,\n this.config.reinforcementFactor,\n this.config.maxHalfLifeMultiplier,\n );\n\n // floor at 0.5: even very old entries keep at least 50% of their score\n const factor = 0.5 + 0.5 * Math.exp(-ageDays / effectiveHL);\n return {\n ...r,\n score: clamp01(r.score * factor, r.score * 0.5),\n };\n });\n\n return decayed.sort((a, b) => b.score - a.score);\n }\n\n /**\n * Apply lifecycle-aware score adjustment (decay + tier floors).\n *\n * This is intentionally lightweight:\n * - reads tier/access metadata (if any)\n * - multiplies scores by max(tierFloor, decayComposite)\n */\n private applyLifecycleBoost(results: RetrievalResult[]): RetrievalResult[] {\n if (!this.decayEngine) return results;\n\n const now = Date.now();\n const pairs = results.map(r => {\n const { memory } = getDecayableFromEntry(r.entry);\n return { r, memory };\n });\n\n const scored = pairs.map(p => ({ memory: p.memory, score: p.r.score }));\n this.decayEngine.applySearchBoost(scored, now);\n\n const boosted = pairs.map((p, i) => ({ ...p.r, score: scored[i].score }));\n return boosted.sort((a, b) => b.score - a.score);\n }\n\n /**\n * Record access stats (access_count, last_accessed_at) and apply tier\n * promotion/demotion for a small number of top results.\n *\n * Note: this writes back to LanceDB via delete+readd; keep it bounded.\n */\n private async recordAccessAndMaybeTransition(results: RetrievalResult[]): Promise<void> {\n if (!this.decayEngine && !this.tierManager) return;\n\n const now = Date.now();\n const toUpdate = results.slice(0, 3);\n\n for (const r of toUpdate) {\n const { memory, meta } = getDecayableFromEntry(r.entry);\n\n // Update access stats in-memory first\n const nextAccess = memory.accessCount + 1;\n meta.access_count = nextAccess;\n meta.last_accessed_at = now;\n if (meta.created_at === undefined && meta.createdAt === undefined) {\n meta.created_at = memory.createdAt;\n }\n if (meta.tier === undefined) {\n meta.tier = memory.tier;\n }\n if (meta.confidence === undefined) {\n meta.confidence = memory.confidence;\n }\n\n const updatedMemory: DecayableMemory = {\n ...memory,\n accessCount: nextAccess,\n lastAccessedAt: now,\n };\n\n // Tier transition (optional)\n if (this.decayEngine && this.tierManager) {\n const ds = this.decayEngine.score(updatedMemory, now);\n const transition = this.tierManager.evaluate(updatedMemory, ds, now);\n if (transition) {\n meta.tier = transition.toTier;\n }\n }\n\n try {\n await this.store.update(r.entry.id, {\n metadata: JSON.stringify(meta),\n });\n } catch {\n // best-effort: ignore\n }\n }\n }\n\n /**\n * MMR-inspired diversity filter: greedily select results that are both\n * relevant (high score) and diverse (low similarity to already-selected).\n *\n * Uses cosine similarity between memory vectors. If two memories have\n * cosine similarity > threshold (default 0.92), the lower-scored one\n * is demoted to the end rather than removed entirely.\n *\n * This prevents top-k from being filled with near-identical entries\n * (e.g. 3 similar \"SVG style\" memories) while keeping them available\n * if the pool is small.\n */\n private applyMMRDiversity(\n results: RetrievalResult[],\n similarityThreshold = 0.85,\n ): RetrievalResult[] {\n if (results.length <= 1) return results;\n\n const selected: RetrievalResult[] = [];\n const deferred: RetrievalResult[] = [];\n\n for (const candidate of results) {\n // Check if this candidate is too similar to any already-selected result\n const tooSimilar = selected.some((s) => {\n // Both must have vectors to compare.\n // LanceDB returns Arrow Vector objects (not plain arrays),\n // so use .length directly and Array.from() for conversion.\n const sVec = s.entry.vector;\n const cVec = candidate.entry.vector;\n if (!sVec?.length || !cVec?.length) return false;\n const sArr = Array.from(sVec as Iterable<number>);\n const cArr = Array.from(cVec as Iterable<number>);\n const sim = cosineSimilarity(sArr, cArr);\n return sim > similarityThreshold;\n });\n\n if (tooSimilar) {\n deferred.push(candidate);\n } else {\n selected.push(candidate);\n }\n }\n // Append deferred results at the end (available but deprioritized)\n return [...selected, ...deferred];\n }\n\n // Update configuration\n updateConfig(newConfig: Partial<RetrievalConfig>): void {\n this.config = { ...this.config, ...newConfig };\n }\n\n // Get current configuration\n getConfig(): RetrievalConfig {\n return { ...this.config };\n }\n\n // Test retrieval system\n async test(query = \"test query\"): Promise<{\n success: boolean;\n mode: string;\n hasFtsSupport: boolean;\n error?: string;\n }> {\n try {\n const results = await this.retrieve({\n query,\n limit: 1,\n });\n\n return {\n success: true,\n mode: this.config.mode,\n hasFtsSupport: this.store.hasFtsSupport,\n };\n } catch (error) {\n return {\n success: false,\n mode: this.config.mode,\n hasFtsSupport: this.store.hasFtsSupport,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n}\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\nexport interface RetrieverLifecycleOptions {\n decayEngine?: DecayEngine;\n tierManager?: TierManager;\n}\n\nexport function createRetriever(\n store: MemoryStore,\n embedder: Embedder,\n config?: Partial<RetrievalConfig>,\n options?: { decayEngine?: DecayEngine | null },\n): MemoryRetriever {\n const fullConfig = { ...DEFAULT_RETRIEVAL_CONFIG, ...config };\n return new MemoryRetriever(store, embedder, fullConfig, options?.decayEngine ?? null);\n}\n"],
5
- "mappings": "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",
6
- "names": ["trackEntry"]
7
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"scopes.d.ts","sourceRoot":"","sources":["../../src/scopes.ts"],"names":[],"mappings":"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"}
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/scopes.ts"],
4
- "sourcesContent": ["// SPDX-License-Identifier: MIT\n/**\n * Multi-Scope Access Control System\n * Manages memory isolation and access permissions\n */\n\nimport { log } from \"./logger.js\";\n\n// ============================================================================\n// Types & Configuration\n// ============================================================================\n\nexport interface ScopeDefinition {\n description: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ScopeConfig {\n default: string;\n definitions: Record<string, ScopeDefinition>;\n agentAccess: Record<string, string[]>;\n}\n\nexport interface ScopeManager {\n getAccessibleScopes(agentId?: string): string[];\n getDefaultScope(agentId?: string): string;\n isAccessible(scope: string, agentId?: string): boolean;\n validateScope(scope: string): boolean;\n getAllScopes(): string[];\n getScopeDefinition(scope: string): ScopeDefinition | undefined;\n}\n\n// ============================================================================\n// Default Configuration\n// ============================================================================\n\nexport const DEFAULT_SCOPE_CONFIG: ScopeConfig = {\n default: \"global\",\n definitions: {\n global: {\n description: \"Shared knowledge across all agents\",\n },\n },\n agentAccess: {},\n};\n\n// ============================================================================\n// Built-in Scope Patterns\n// ============================================================================\n\nconst SCOPE_PATTERNS = {\n GLOBAL: \"global\",\n AGENT: (agentId: string) => `agent:${agentId}`,\n CUSTOM: (name: string) => `custom:${name}`,\n PROJECT: (projectId: string) => `project:${projectId}`,\n USER: (userId: string) => `user:${userId}`,\n};\n\n// ============================================================================\n// Scope Manager Implementation\n// ============================================================================\n\nexport class MemoryScopeManager implements ScopeManager {\n private config: ScopeConfig;\n\n constructor(config: Partial<ScopeConfig> = {}) {\n this.config = {\n default: config.default || DEFAULT_SCOPE_CONFIG.default,\n definitions: {\n ...DEFAULT_SCOPE_CONFIG.definitions,\n ...config.definitions,\n },\n agentAccess: {\n ...DEFAULT_SCOPE_CONFIG.agentAccess,\n ...config.agentAccess,\n },\n };\n\n // Ensure global scope always exists\n if (!this.config.definitions.global) {\n this.config.definitions.global = {\n description: \"Shared knowledge across all agents\",\n };\n }\n\n this.validateConfiguration();\n }\n\n private validateConfiguration(): void {\n // Validate default scope exists in definitions\n if (!this.config.definitions[this.config.default]) {\n throw new Error(`Default scope '${this.config.default}' not found in definitions`);\n }\n\n // Validate agent access scopes exist in definitions\n for (const [agentId, scopes] of Object.entries(this.config.agentAccess)) {\n for (const scope of scopes) {\n if (!this.config.definitions[scope] && !this.isBuiltInScope(scope)) {\n log.warn(`Agent '${agentId}' has access to undefined scope '${scope}'`);\n }\n }\n }\n }\n\n private isBuiltInScope(scope: string): boolean {\n return (\n scope === \"global\" ||\n scope.startsWith(\"agent:\") ||\n scope.startsWith(\"custom:\") ||\n scope.startsWith(\"project:\") ||\n scope.startsWith(\"user:\")\n );\n }\n\n getAccessibleScopes(agentId?: string): string[] {\n if (!agentId) {\n // No agent specified, return all scopes\n return this.getAllScopes();\n }\n\n // Check explicit agent access configuration\n const explicitAccess = this.config.agentAccess[agentId];\n if (explicitAccess) {\n return explicitAccess;\n }\n\n // Default access: global + agent-specific scope\n const defaultScopes = [\"global\"];\n const agentScope = SCOPE_PATTERNS.AGENT(agentId);\n\n // Only include agent scope if it already exists \u2014 don't mutate config as a side effect\n if (this.config.definitions[agentScope] || this.isBuiltInScope(agentScope)) {\n defaultScopes.push(agentScope);\n }\n\n return defaultScopes;\n }\n\n getDefaultScope(agentId?: string): string {\n if (!agentId) {\n return this.config.default;\n }\n\n // For agents, default to their private scope if they have access to it\n const agentScope = SCOPE_PATTERNS.AGENT(agentId);\n const accessibleScopes = this.getAccessibleScopes(agentId);\n\n if (accessibleScopes.includes(agentScope)) {\n return agentScope;\n }\n\n return this.config.default;\n }\n\n isAccessible(scope: string, agentId?: string): boolean {\n if (!agentId) {\n // No agent specified, allow access to all valid scopes\n return this.validateScope(scope);\n }\n\n const accessibleScopes = this.getAccessibleScopes(agentId);\n return accessibleScopes.includes(scope);\n }\n\n validateScope(scope: string): boolean {\n if (!scope || typeof scope !== \"string\" || scope.trim().length === 0) {\n return false;\n }\n\n const trimmedScope = scope.trim();\n\n // Check if scope is defined or is a built-in pattern\n return (\n this.config.definitions[trimmedScope] !== undefined ||\n this.isBuiltInScope(trimmedScope)\n );\n }\n\n getAllScopes(): string[] {\n return Object.keys(this.config.definitions);\n }\n\n getScopeDefinition(scope: string): ScopeDefinition | undefined {\n return this.config.definitions[scope];\n }\n\n // Management methods\n\n addScopeDefinition(scope: string, definition: ScopeDefinition): void {\n if (!this.validateScopeFormat(scope)) {\n throw new Error(`Invalid scope format: ${scope}`);\n }\n\n this.config.definitions[scope] = definition;\n }\n\n removeScopeDefinition(scope: string): boolean {\n if (scope === \"global\") {\n throw new Error(\"Cannot remove global scope\");\n }\n\n if (!this.config.definitions[scope]) {\n return false;\n }\n\n delete this.config.definitions[scope];\n\n // Clean up agent access references\n for (const [agentId, scopes] of Object.entries(this.config.agentAccess)) {\n const filtered = scopes.filter(s => s !== scope);\n if (filtered.length !== scopes.length) {\n this.config.agentAccess[agentId] = filtered;\n }\n }\n\n return true;\n }\n\n setAgentAccess(agentId: string, scopes: string[]): void {\n if (!agentId || typeof agentId !== \"string\") {\n throw new Error(\"Invalid agent ID\");\n }\n\n // Validate all scopes\n for (const scope of scopes) {\n if (!this.validateScope(scope)) {\n throw new Error(`Invalid scope: ${scope}`);\n }\n }\n\n this.config.agentAccess[agentId] = [...scopes];\n }\n\n removeAgentAccess(agentId: string): boolean {\n if (!this.config.agentAccess[agentId]) {\n return false;\n }\n\n delete this.config.agentAccess[agentId];\n return true;\n }\n\n private validateScopeFormat(scope: string): boolean {\n if (!scope || typeof scope !== \"string\") {\n return false;\n }\n\n const trimmed = scope.trim();\n\n // Basic format validation\n if (trimmed.length === 0 || trimmed.length > 100) {\n return false;\n }\n\n // Allow alphanumeric, hyphens, underscores, colons, and dots\n const validFormat = /^[a-zA-Z0-9._:-]+$/.test(trimmed);\n return validFormat;\n }\n\n // Export/Import configuration\n\n exportConfig(): ScopeConfig {\n return JSON.parse(JSON.stringify(this.config));\n }\n\n importConfig(config: Partial<ScopeConfig>): void {\n this.config = {\n default: config.default || this.config.default,\n definitions: {\n ...this.config.definitions,\n ...config.definitions,\n },\n agentAccess: {\n ...this.config.agentAccess,\n ...config.agentAccess,\n },\n };\n\n this.validateConfiguration();\n }\n\n // Statistics\n\n getStats(): {\n totalScopes: number;\n agentsWithCustomAccess: number;\n scopesByType: Record<string, number>;\n } {\n const scopes = this.getAllScopes();\n const scopesByType: Record<string, number> = {\n global: 0,\n agent: 0,\n custom: 0,\n project: 0,\n user: 0,\n other: 0,\n };\n\n for (const scope of scopes) {\n if (scope === \"global\") {\n scopesByType.global++;\n } else if (scope.startsWith(\"agent:\")) {\n scopesByType.agent++;\n } else if (scope.startsWith(\"custom:\")) {\n scopesByType.custom++;\n } else if (scope.startsWith(\"project:\")) {\n scopesByType.project++;\n } else if (scope.startsWith(\"user:\")) {\n scopesByType.user++;\n } else {\n scopesByType.other++;\n }\n }\n\n return {\n totalScopes: scopes.length,\n agentsWithCustomAccess: Object.keys(this.config.agentAccess).length,\n scopesByType,\n };\n }\n}\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\nexport function createScopeManager(config?: Partial<ScopeConfig>): MemoryScopeManager {\n return new MemoryScopeManager(config);\n}\n\nexport function createAgentScope(agentId: string): string {\n return SCOPE_PATTERNS.AGENT(agentId);\n}\n\nexport function createCustomScope(name: string): string {\n return SCOPE_PATTERNS.CUSTOM(name);\n}\n\nexport function createProjectScope(projectId: string): string {\n return SCOPE_PATTERNS.PROJECT(projectId);\n}\n\nexport function createUserScope(userId: string): string {\n return SCOPE_PATTERNS.USER(userId);\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\nexport function parseScopeId(scope: string): { type: string; id: string } | null {\n if (scope === \"global\") {\n return { type: \"global\", id: \"\" };\n }\n\n const colonIndex = scope.indexOf(\":\");\n if (colonIndex === -1) {\n return null;\n }\n\n return {\n type: scope.substring(0, colonIndex),\n id: scope.substring(colonIndex + 1),\n };\n}\n\nexport function isScopeAccessible(scope: string, allowedScopes: string[]): boolean {\n return allowedScopes.includes(scope);\n}\n\nexport function filterScopesForAgent(scopes: string[], agentId?: string, scopeManager?: ScopeManager): string[] {\n if (!scopeManager || !agentId) {\n return scopes;\n }\n\n return scopes.filter(scope => scopeManager.isAccessible(scope, agentId));\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"self-improvement-files.d.ts","sourceRoot":"","sources":["../../src/self-improvement-files.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,0BAA0B,wLAI4B,CAAC;AAEpE,eAAO,MAAM,uBAAuB,iKAIuB,CAAC;AAyC5D,wBAAsB,kCAAkC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBvF;AAED,MAAM,WAAW,gCAAgC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,0BAA0B,CAAC,MAAM,EAAE,gCAAgC,GAAG,OAAO,CAAC;IAClG,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAqDD"}
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/self-improvement-files.ts"],
4
- "sourcesContent": ["// SPDX-License-Identifier: LicenseRef-Mnemo-Pro\nimport { appendFile, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport const DEFAULT_LEARNINGS_TEMPLATE = `# Learnings\n\nAppend structured entries:\n- LRN-YYYYMMDD-XXX for corrections / best practices / knowledge gaps\n- Include summary, details, suggested action, metadata, and status`;\n\nexport const DEFAULT_ERRORS_TEMPLATE = `# Errors\n\nAppend structured entries:\n- ERR-YYYYMMDD-XXX for command/tool/integration failures\n- Include symptom, context, probable cause, and prevention`;\n\nconst fileWriteQueues = new Map<string, Promise<void>>();\n\nasync function withFileWriteQueue<T>(filePath: string, action: () => Promise<T>): Promise<T> {\n const previous = fileWriteQueues.get(filePath) ?? Promise.resolve();\n let release: (() => void) | undefined;\n const lock = new Promise<void>((resolve) => {\n release = resolve;\n });\n const next = previous.then(() => lock);\n fileWriteQueues.set(filePath, next);\n\n await previous;\n try {\n return await action();\n } finally {\n release?.();\n if (fileWriteQueues.get(filePath) === next) {\n fileWriteQueues.delete(filePath);\n }\n }\n}\n\nfunction todayYmd(): string {\n return new Date().toISOString().slice(0, 10).replace(/-/g, \"\");\n}\n\nasync function nextLearningId(filePath: string, prefix: \"LRN\" | \"ERR\"): Promise<string> {\n const date = todayYmd();\n let count = 0;\n try {\n const content = await readFile(filePath, \"utf-8\");\n const matches = content.match(new RegExp(`\\\\[${prefix}-${date}-\\\\d{3}\\\\]`, \"g\"));\n count = matches?.length ?? 0;\n } catch {\n // ignore\n }\n return `${prefix}-${date}-${String(count + 1).padStart(3, \"0\")}`;\n}\n\nexport async function ensureSelfImprovementLearningFiles(baseDir: string): Promise<void> {\n const learningsDir = join(baseDir, \".learnings\");\n await mkdir(learningsDir, { recursive: true });\n\n const ensureFile = async (filePath: string, content: string) => {\n try {\n const existing = await readFile(filePath, \"utf-8\");\n if (existing.trim().length > 0) return;\n } catch {\n // write default below\n }\n await writeFile(filePath, `${content.trim()}\\n`, \"utf-8\");\n };\n\n await ensureFile(join(learningsDir, \"LEARNINGS.md\"), DEFAULT_LEARNINGS_TEMPLATE);\n await ensureFile(join(learningsDir, \"ERRORS.md\"), DEFAULT_ERRORS_TEMPLATE);\n}\n\nexport interface AppendSelfImprovementEntryParams {\n baseDir: string;\n type: \"learning\" | \"error\";\n summary: string;\n details?: string;\n suggestedAction?: string;\n category?: string;\n area?: string;\n priority?: string;\n status?: string;\n source?: string;\n}\n\nexport async function appendSelfImprovementEntry(params: AppendSelfImprovementEntryParams): Promise<{\n id: string;\n filePath: string;\n}> {\n const {\n baseDir,\n type,\n summary,\n details = \"\",\n suggestedAction = \"\",\n category = \"best_practice\",\n area = \"config\",\n priority = \"medium\",\n status = \"pending\",\n source = \"mnemo/self_improvement_log\",\n } = params;\n\n await ensureSelfImprovementLearningFiles(baseDir);\n const learningsDir = join(baseDir, \".learnings\");\n const fileName = type === \"learning\" ? \"LEARNINGS.md\" : \"ERRORS.md\";\n const filePath = join(learningsDir, fileName);\n const idPrefix = type === \"learning\" ? \"LRN\" : \"ERR\";\n\n const id = await withFileWriteQueue(filePath, async () => {\n const entryId = await nextLearningId(filePath, idPrefix);\n const nowIso = new Date().toISOString();\n const titleSuffix = type === \"learning\" ? ` ${category}` : \"\";\n const entry = [\n `## [${entryId}]${titleSuffix}`,\n \"\",\n `**Logged**: ${nowIso}`,\n `**Priority**: ${priority}`,\n `**Status**: ${status}`,\n `**Area**: ${area}`,\n \"\",\n \"### Summary\",\n summary.trim(),\n \"\",\n \"### Details\",\n details.trim() || \"-\",\n \"\",\n \"### Suggested Action\",\n suggestedAction.trim() || \"-\",\n \"\",\n \"### Metadata\",\n `- Source: ${source}`,\n \"---\",\n \"\",\n ].join(\"\\n\");\n const prev = await readFile(filePath, \"utf-8\").catch(() => \"\");\n const separator = prev.trimEnd().length > 0 ? \"\\n\\n\" : \"\";\n await appendFile(filePath, `${separator}${entry}`, \"utf-8\");\n return entryId;\n });\n\n return { id, filePath };\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"semantic-gate.d.ts","sourceRoot":"","sources":["../../src/semantic-gate.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAuC9C,qBAAa,YAAY;IAMrB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAL3B,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAGhB,QAAQ,EAAE,QAAQ,EACnC,SAAS,SAAO;YAKJ,iBAAiB;YAWjB,cAAc;IAS5B;;;OAGG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;YA2BpD,WAAW;CAS1B"}
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/semantic-gate.ts"],
4
- "sourcesContent": ["// SPDX-License-Identifier: MIT\n/**\n * Semantic Noise Gate\n *\n * Pre-filters memory candidates by checking their embedding similarity against\n * domain-relevant anchor texts. Fragments that are too far from any anchor are\n * rejected as noise before reaching the dedup or store pipeline.\n */\n\nimport type { Embedder } from \"./embedder.js\";\nimport { appendFile, mkdir } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join, dirname } from \"node:path\";\n\n// ============================================================================\n// Anchor Texts\n// ============================================================================\n\nconst ANCHOR_TEXTS = [\n \"\u6295\u8D44\u51B3\u7B56 \u4F30\u503C\u5206\u6790 \u6301\u4ED3\u7BA1\u7406 \u5C3D\u804C\u8C03\u67E5\",\n \"\u4E2A\u4EBA\u504F\u597D \u65E5\u5E38\u4E60\u60EF \u4EBA\u9645\u5173\u7CFB \u751F\u6D3B\u65B9\u5F0F\",\n \"\u6280\u672F\u67B6\u6784 \u7CFB\u7EDF\u8BBE\u8BA1 \u4EE3\u7801\u5B9E\u73B0 \u5DE5\u7A0B\u4F18\u5316\",\n] as const;\n\n// ============================================================================\n// Cosine Similarity\n// ============================================================================\n\nfunction cosineSimilarity(a: number[], b: number[]): number {\n if (a.length !== b.length || a.length === 0) return 0;\n let dot = 0;\n let normA = 0;\n let normB = 0;\n for (let i = 0; i < a.length; i++) {\n dot += a[i] * b[i];\n normA += a[i] * a[i];\n normB += b[i] * b[i];\n }\n const denom = Math.sqrt(normA) * Math.sqrt(normB);\n return denom === 0 ? 0 : dot / denom;\n}\n\n// ============================================================================\n// Semantic Gate\n// ============================================================================\n\nconst FILTER_LOG_PATH = join(homedir(), \".openclaw\", \"memory\", \"store-filtered.log\");\n\nexport class SemanticGate {\n private anchorEmbeddings: number[][] | null = null;\n private initPromise: Promise<void> | null = null;\n private readonly threshold: number;\n\n constructor(\n private readonly embedder: Embedder,\n threshold = 0.20,\n ) {\n this.threshold = threshold;\n }\n\n private async ensureInitialized(): Promise<void> {\n if (this.anchorEmbeddings) return;\n if (this.initPromise) return this.initPromise;\n\n this.initPromise = this.computeAnchors().catch((err) => {\n this.initPromise = null;\n throw err;\n });\n return this.initPromise;\n }\n\n private async computeAnchors(): Promise<void> {\n const embeddings: number[][] = [];\n for (const text of ANCHOR_TEXTS) {\n const vec = await this.embedder.embed(text);\n embeddings.push(vec);\n }\n this.anchorEmbeddings = embeddings;\n }\n\n /**\n * Check whether a memory vector passes the semantic gate.\n * Returns true if the memory is relevant enough to persist.\n */\n async shouldPass(vector: number[], text: string): Promise<boolean> {\n try {\n await this.ensureInitialized();\n } catch {\n // If anchor computation fails, pass everything through\n return true;\n }\n\n if (!this.anchorEmbeddings || this.anchorEmbeddings.length === 0) {\n return true;\n }\n\n let maxSim = 0;\n for (const anchor of this.anchorEmbeddings) {\n const sim = cosineSimilarity(vector, anchor);\n if (sim > maxSim) maxSim = sim;\n }\n\n if (maxSim < this.threshold) {\n // Log filtered content\n this.logFiltered(text, maxSim).catch(() => {});\n return false;\n }\n\n return true;\n }\n\n private async logFiltered(text: string, maxSim: number): Promise<void> {\n try {\n await mkdir(dirname(FILTER_LOG_PATH), { recursive: true });\n const line = `${new Date().toISOString()} maxSim=${maxSim.toFixed(4)} text=${text.slice(0, 200).replace(/\\n/g, \" \")}\\n`;\n await appendFile(FILTER_LOG_PATH, line, \"utf8\");\n } catch {\n // Non-critical\n }\n }\n}\n"],
5
- "mappings": "AAUA,SAAS,YAAY,aAAa;AAClC,SAAS,eAAe;AACxB,SAAS,MAAM,eAAe;AAM9B,MAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF;AAMA,SAAS,iBAAiB,GAAa,GAAqB;AAC1D,MAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAG,QAAO;AACpD,MAAI,MAAM;AACV,MAAI,QAAQ;AACZ,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,WAAO,EAAE,CAAC,IAAI,EAAE,CAAC;AACjB,aAAS,EAAE,CAAC,IAAI,EAAE,CAAC;AACnB,aAAS,EAAE,CAAC,IAAI,EAAE,CAAC;AAAA,EACrB;AACA,QAAM,QAAQ,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK;AAChD,SAAO,UAAU,IAAI,IAAI,MAAM;AACjC;AAMA,MAAM,kBAAkB,KAAK,QAAQ,GAAG,aAAa,UAAU,oBAAoB;AAE5E,MAAM,aAAa;AAAA,EAKxB,YACmB,UACjB,YAAY,KACZ;AAFiB;AAGjB,SAAK,YAAY;AAAA,EACnB;AAAA,EATQ,mBAAsC;AAAA,EACtC,cAAoC;AAAA,EAC3B;AAAA,EASjB,MAAc,oBAAmC;AAC/C,QAAI,KAAK,iBAAkB;AAC3B,QAAI,KAAK,YAAa,QAAO,KAAK;AAElC,SAAK,cAAc,KAAK,eAAe,EAAE,MAAM,CAAC,QAAQ;AACtD,WAAK,cAAc;AACnB,YAAM;AAAA,IACR,CAAC;AACD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,iBAAgC;AAC5C,UAAM,aAAyB,CAAC;AAChC,eAAW,QAAQ,cAAc;AAC/B,YAAM,MAAM,MAAM,KAAK,SAAS,MAAM,IAAI;AAC1C,iBAAW,KAAK,GAAG;AAAA,IACrB;AACA,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAW,QAAkB,MAAgC;AACjE,QAAI;AACF,YAAM,KAAK,kBAAkB;AAAA,IAC/B,QAAQ;AAEN,aAAO;AAAA,IACT;AAEA,QAAI,CAAC,KAAK,oBAAoB,KAAK,iBAAiB,WAAW,GAAG;AAChE,aAAO;AAAA,IACT;AAEA,QAAI,SAAS;AACb,eAAW,UAAU,KAAK,kBAAkB;AAC1C,YAAM,MAAM,iBAAiB,QAAQ,MAAM;AAC3C,UAAI,MAAM,OAAQ,UAAS;AAAA,IAC7B;AAEA,QAAI,SAAS,KAAK,WAAW;AAE3B,WAAK,YAAY,MAAM,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAC7C,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,YAAY,MAAc,QAA+B;AACrE,QAAI;AACF,YAAM,MAAM,QAAQ,eAAe,GAAG,EAAE,WAAW,KAAK,CAAC;AACzD,YAAM,OAAO,IAAG,oBAAI,KAAK,GAAE,YAAY,CAAC,WAAW,OAAO,QAAQ,CAAC,CAAC,SAAS,KAAK,MAAM,GAAG,GAAG,EAAE,QAAQ,OAAO,GAAG,CAAC;AAAA;AACnH,YAAM,WAAW,iBAAiB,MAAM,MAAM;AAAA,IAChD,QAAQ;AAAA,IAER;AAAA,EACF;AACF;",
6
- "names": []
7
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"session-recovery.d.ts","sourceRoot":"","sources":["../../src/session-recovery.ts"],"names":[],"mappings":"AASA,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGzD;AAuCD,wBAAgB,kCAAkC,CAAC,MAAM,EAAE;IACzD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,GAAG,EAAE,OAAO,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,MAAM,EAAE,CAgFX"}
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/session-recovery.ts"],
4
- "sourcesContent": ["// SPDX-License-Identifier: LicenseRef-Mnemo-Pro\nimport { dirname, join } from \"node:path\";\n\nfunction asNonEmptyString(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length ? trimmed : undefined;\n}\n\nexport function stripResetSuffix(fileName: string): string {\n const resetIndex = fileName.indexOf(\".reset.\");\n return resetIndex === -1 ? fileName : fileName.slice(0, resetIndex);\n}\n\nfunction deriveOpenClawHomeFromWorkspacePath(workspacePath: string): string | undefined {\n const normalized = workspacePath.trim().replace(/[\\\\/]+$/, \"\");\n if (!normalized) return undefined;\n const matched = normalized.match(/^(.*?)[\\\\/]workspace(?:[\\\\/].*)?$/);\n if (!matched || !matched[1]) return undefined;\n const home = matched[1].trim();\n return home.length ? home : undefined;\n}\n\nfunction deriveOpenClawHomeFromSessionFilePath(sessionFilePath: string): string | undefined {\n const normalized = sessionFilePath.trim();\n if (!normalized) return undefined;\n const matched = normalized.match(/^(.*?)[\\\\/]agents[\\\\/][^\\\\/]+[\\\\/]sessions(?:[\\\\/][^\\\\/]+)?$/);\n if (!matched || !matched[1]) return undefined;\n const home = matched[1].trim();\n return home.length ? home : undefined;\n}\n\nfunction listConfiguredAgentIds(cfg: unknown): string[] {\n try {\n const root = cfg as Record<string, unknown>;\n const agents = root.agents as Record<string, unknown> | undefined;\n const list = agents?.list as unknown;\n if (!Array.isArray(list)) return [];\n\n const ids: string[] = [];\n for (const item of list) {\n if (!item || typeof item !== \"object\") continue;\n const id = asNonEmptyString((item as Record<string, unknown>).id);\n if (id) ids.push(id);\n }\n return ids;\n } catch {\n return [];\n }\n}\n\nexport function resolveReflectionSessionSearchDirs(params: {\n context: Record<string, unknown>;\n cfg: unknown;\n workspaceDir: string;\n currentSessionFile?: string;\n sourceAgentId?: string;\n}): string[] {\n const out: string[] = [];\n const seen = new Set<string>();\n const addDir = (value: string | undefined) => {\n const dir = asNonEmptyString(value);\n if (!dir || seen.has(dir)) return;\n seen.add(dir);\n out.push(dir);\n };\n const addHome = (homes: string[], value: string | undefined) => {\n const home = asNonEmptyString(value);\n if (!home || homes.includes(home)) return;\n homes.push(home);\n };\n const addAgentId = (agentIds: string[], value: string | undefined) => {\n const agentId = asNonEmptyString(value);\n if (!agentId || agentId.includes(\"/\") || agentId.includes(\"\\\\\") || agentIds.includes(agentId)) return;\n agentIds.push(agentId);\n };\n\n const previousSessionEntry = (params.context.previousSessionEntry || {}) as Record<string, unknown>;\n const sessionEntry = (params.context.sessionEntry || {}) as Record<string, unknown>;\n const sessionEntries = [previousSessionEntry, sessionEntry];\n\n if (params.currentSessionFile) addDir(dirname(params.currentSessionFile));\n for (const entry of sessionEntries) {\n const file = asNonEmptyString(entry.sessionFile);\n if (file) addDir(dirname(file));\n addDir(asNonEmptyString(entry.sessionsDir));\n addDir(asNonEmptyString(entry.sessionDir));\n }\n addDir(join(params.workspaceDir, \"sessions\"));\n\n const openclawHomes: string[] = [];\n addHome(openclawHomes, asNonEmptyString(process.env.OPENCLAW_HOME));\n addHome(openclawHomes, deriveOpenClawHomeFromWorkspacePath(params.workspaceDir));\n if (params.currentSessionFile) {\n addHome(openclawHomes, deriveOpenClawHomeFromSessionFilePath(params.currentSessionFile));\n }\n for (const entry of sessionEntries) {\n const entryFile = asNonEmptyString(entry.sessionFile);\n if (entryFile) addHome(openclawHomes, deriveOpenClawHomeFromSessionFilePath(entryFile));\n }\n try {\n const root = params.cfg as Record<string, unknown>;\n const agents = root.agents as Record<string, unknown> | undefined;\n const defaults = agents?.defaults as Record<string, unknown> | undefined;\n const defaultWorkspace = asNonEmptyString(defaults?.workspace);\n if (defaultWorkspace) addHome(openclawHomes, deriveOpenClawHomeFromWorkspacePath(defaultWorkspace));\n\n const list = agents?.list as unknown;\n if (Array.isArray(list)) {\n for (const item of list) {\n if (!item || typeof item !== \"object\") continue;\n const workspace = asNonEmptyString((item as Record<string, unknown>).workspace);\n if (workspace) addHome(openclawHomes, deriveOpenClawHomeFromWorkspacePath(workspace));\n }\n }\n } catch {\n // ignore\n }\n\n const agentIds: string[] = [];\n addAgentId(agentIds, params.sourceAgentId);\n addAgentId(agentIds, asNonEmptyString(params.context.agentId));\n for (const entry of sessionEntries) {\n addAgentId(agentIds, asNonEmptyString(entry.agentId));\n }\n for (const configuredId of listConfiguredAgentIds(params.cfg)) {\n addAgentId(agentIds, configuredId);\n }\n addAgentId(agentIds, \"main\");\n\n for (const home of openclawHomes) {\n for (const agentId of agentIds) {\n addDir(join(home, \"agents\", agentId, \"sessions\"));\n }\n }\n\n return out;\n}\n"],
5
- "mappings": "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",
6
- "names": ["agentIds"]
7
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"smart-extractor.d.ts","sourceRoot":"","sources":["../../src/smart-extractor.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAOjD,OAAO,EAIL,KAAK,eAAe,EAMrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAmChE,MAAM,WAAW,oBAAoB;IACnC,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uBAAuB;IACvB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,2FAA2F;IAC3F,SAAS,CAAC,EAAE,kBAAkB,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,qBAAa,cAAc;IAKvB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,MAAM;IAPhB,OAAO,CAAC,GAAG,CAAwB;IACnC,OAAO,CAAC,QAAQ,CAAwB;gBAG9B,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,SAAS,EACd,MAAM,GAAE,oBAAyB;IAU3C;;;OAGG;IACG,iBAAiB,CACrB,gBAAgB,EAAE,MAAM,EACxB,UAAU,GAAE,MAAkB,EAC9B,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,eAAe,CAAC;IA8C3B;;;;OAIG;IACG,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAiChE;;;OAGG;YACW,YAAY;IAoB1B;;OAEG;YACW,iBAAiB;IAyF/B;;OAEG;YACW,gBAAgB;IAqG9B;;OAEG;YACW,WAAW;YAqBX,gBAAgB;IA0E9B;;OAEG;YACW,kBAAkB;IAuChC;;OAEG;YACW,WAAW;IA4GzB;;OAEG;YACW,aAAa;IA0B3B;;;OAGG;YACW,mBAAmB;IAsCjC;;;OAGG;YACW,gBAAgB;IAyF9B;;OAEG;YACW,cAAc;IA0C5B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAqB1B;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAkB7B"}
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/smart-extractor.ts"],
4
- "sourcesContent": ["// SPDX-License-Identifier: MIT\n/**\n * Smart Memory Extractor \u2014 LLM-powered extraction pipeline\n * Replaces regex-triggered capture with intelligent 6-category extraction.\n *\n * Pipeline: conversation \u2192 LLM extract \u2192 candidates \u2192 dedup \u2192 persist\n *\n */\n\nimport type { MemoryStore, MemorySearchResult } from \"./store.js\";\nimport type { Embedder } from \"./embedder.js\";\nimport type { LlmClient } from \"./llm-client.js\";\nimport {\n buildExtractionPrompt,\n buildChineseExtractionPrompt,\n buildDedupPrompt,\n buildMergePrompt,\n} from \"./extraction-prompts.js\";\nimport {\n type CandidateMemory,\n type DedupDecision,\n type DedupResult,\n type ExtractionStats,\n type MemoryCategory,\n ALWAYS_MERGE_CATEGORIES,\n MERGE_SUPPORTED_CATEGORIES,\n MEMORY_CATEGORIES,\n normalizeCategory,\n} from \"./memory-categories.js\";\nimport { isNoise } from \"./noise-filter.js\";\nimport type { NoisePrototypeBank } from \"./noise-prototypes.js\";\nimport { buildSmartMetadata, parseSmartMetadata, stringifySmartMetadata, parseSupportInfo, updateSupportStats } from \"./smart-metadata.js\";\nimport { log as _log } from \"./logger.js\";\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst SIMILARITY_THRESHOLD = 0.7;\nconst MAX_SIMILAR_FOR_PROMPT = 3;\nconst MAX_MEMORIES_PER_EXTRACTION = 5;\nconst VALID_DECISIONS = new Set<string>([\"create\", \"merge\", \"skip\", \"support\", \"contextualize\", \"contradict\"]);\n\n// ============================================================================\n// CJK Detection\n// ============================================================================\n\n/**\n * Detect whether a text is predominantly CJK (Chinese/Japanese/Korean).\n * Returns true if CJK characters make up > 30% of non-whitespace characters.\n */\nfunction isCjkDominant(text: string): boolean {\n // CJK Unified Ideographs + CJK Extension A/B + CJK Compatibility + Kana + Hangul\n const cjkRegex = /[\\u4e00-\\u9fff\\u3400-\\u4dbf\\u3040-\\u309f\\u30a0-\\u30ff\\uac00-\\ud7af\\uf900-\\ufaff]/g;\n const nonWhitespace = text.replace(/\\s/g, \"\");\n if (nonWhitespace.length === 0) return false;\n const cjkMatches = nonWhitespace.match(cjkRegex);\n const cjkCount = cjkMatches ? cjkMatches.length : 0;\n return cjkCount / nonWhitespace.length > 0.3;\n}\n\n// ============================================================================\n// Smart Extractor\n// ============================================================================\n\nexport interface SmartExtractorConfig {\n /** User identifier for extraction prompt. */\n user?: string;\n /** Minimum conversation messages before extraction triggers. */\n extractMinMessages?: number;\n /** Maximum characters of conversation text to process. */\n extractMaxChars?: number;\n /** Default scope for new memories. */\n defaultScope?: string;\n /** Logger function. */\n log?: (msg: string) => void;\n /** Debug logger function. */\n debugLog?: (msg: string) => void;\n /** Optional embedding-based noise prototype bank for language-agnostic noise filtering. */\n noiseBank?: NoisePrototypeBank;\n}\n\nexport interface ExtractPersistOptions {\n /** Target scope for newly created memories. */\n scope?: string;\n /** Scopes visible to the current agent for dedup/merge. */\n scopeFilter?: string[];\n}\n\nexport class SmartExtractor {\n private log: (msg: string) => void;\n private debugLog: (msg: string) => void;\n\n constructor(\n private store: MemoryStore,\n private embedder: Embedder,\n private llm: LlmClient,\n private config: SmartExtractorConfig = {},\n ) {\n this.log = config.log ?? ((msg: string) => _log.info(msg));\n this.debugLog = config.debugLog ?? (() => { });\n }\n\n // --------------------------------------------------------------------------\n // Main entry point\n // --------------------------------------------------------------------------\n\n /**\n * Extract memories from a conversation text and persist them.\n * Returns extraction statistics.\n */\n async extractAndPersist(\n conversationText: string,\n sessionKey: string = \"unknown\",\n options: ExtractPersistOptions = {},\n ): Promise<ExtractionStats> {\n const stats: ExtractionStats = { created: 0, merged: 0, skipped: 0 };\n const targetScope = options.scope ?? this.config.defaultScope ?? \"global\";\n const scopeFilter =\n options.scopeFilter && options.scopeFilter.length > 0\n ? options.scopeFilter\n : [targetScope];\n\n // Step 1: LLM extraction\n const candidates = await this.extractCandidates(conversationText);\n\n if (candidates.length === 0) {\n this.log(\"memory-pro: smart-extractor: no memories extracted\");\n // LLM returned zero candidates \u2192 strongest noise signal \u2192 feedback to noise bank\n this.learnAsNoise(conversationText);\n return stats;\n }\n\n this.log(\n `memory-pro: smart-extractor: extracted ${candidates.length} candidate(s)`,\n );\n\n // Step 2: Process each candidate through dedup pipeline\n for (const candidate of candidates.slice(0, MAX_MEMORIES_PER_EXTRACTION)) {\n try {\n await this.processCandidate(\n candidate,\n sessionKey,\n stats,\n targetScope,\n scopeFilter,\n );\n } catch (err) {\n this.log(\n `memory-pro: smart-extractor: failed to process candidate [${candidate.category}]: ${String(err)}`,\n );\n }\n }\n\n return stats;\n }\n\n // --------------------------------------------------------------------------\n // Embedding Noise Pre-Filter\n // --------------------------------------------------------------------------\n\n /**\n * Filter out texts that match noise prototypes by embedding similarity.\n * Long texts (>300 chars) are passed through without checking.\n * Only active when noiseBank is configured and initialized.\n */\n async filterNoiseByEmbedding(texts: string[]): Promise<string[]> {\n const noiseBank = this.config.noiseBank;\n if (!noiseBank || !noiseBank.initialized) return texts;\n\n const result: string[] = [];\n for (const text of texts) {\n // Very short texts lack semantic signal \u2014 skip noise check to avoid false positives\n if (text.length <= 8) {\n result.push(text);\n continue;\n }\n // Long texts are unlikely to be pure noise queries\n if (text.length > 300) {\n result.push(text);\n continue;\n }\n try {\n const vec = await this.embedder.embed(text);\n if (!vec || vec.length === 0 || !noiseBank.isNoise(vec)) {\n result.push(text);\n } else {\n this.debugLog(\n `mnemo: smart-extractor: embedding noise filtered: ${text.slice(0, 80)}`,\n );\n }\n } catch {\n // Embedding failed \u2014 pass text through\n result.push(text);\n }\n }\n return result;\n }\n\n /**\n * Feed back conversation text to the noise prototype bank.\n * Called when LLM extraction returns zero candidates (strongest noise signal).\n */\n private async learnAsNoise(conversationText: string): Promise<void> {\n const noiseBank = this.config.noiseBank;\n if (!noiseBank || !noiseBank.initialized) return;\n\n try {\n const tail = conversationText.slice(-300);\n const vec = await this.embedder.embed(tail);\n if (vec && vec.length > 0) {\n noiseBank.learn(vec);\n this.debugLog(\"mnemo: smart-extractor: learned noise from zero-extraction\");\n }\n } catch {\n // Non-critical \u2014 silently skip\n }\n }\n\n // --------------------------------------------------------------------------\n // Step 1: LLM Extraction\n // --------------------------------------------------------------------------\n\n /**\n * Call LLM to extract candidate memories from conversation text.\n */\n private async extractCandidates(\n conversationText: string,\n ): Promise<CandidateMemory[]> {\n const maxChars = this.config.extractMaxChars ?? 8000;\n const truncated =\n conversationText.length > maxChars\n ? conversationText.slice(-maxChars)\n : conversationText;\n\n const user = this.config.user ?? \"User\";\n const prompt = isCjkDominant(truncated)\n ? buildChineseExtractionPrompt(truncated, user)\n : buildExtractionPrompt(truncated, user);\n\n const result = await this.llm.completeJson<{\n memories: Array<{\n category: string;\n abstract: string;\n overview: string;\n content: string;\n }>;\n }>(prompt, \"extract-candidates\");\n\n if (!result) {\n this.debugLog(\n \"mnemo: smart-extractor: extract-candidates returned null\",\n );\n return [];\n }\n if (!result.memories || !Array.isArray(result.memories)) {\n this.debugLog(\n `mnemo: smart-extractor: extract-candidates returned unexpected shape keys=${Object.keys(result).join(\",\") || \"(none)\"}`,\n );\n return [];\n }\n\n this.debugLog(\n `mnemo: smart-extractor: extract-candidates raw memories=${result.memories.length}`,\n );\n\n // Validate and normalize candidates\n const candidates: CandidateMemory[] = [];\n let invalidCategoryCount = 0;\n let shortAbstractCount = 0;\n let noiseAbstractCount = 0;\n for (const raw of result.memories) {\n const category = normalizeCategory(raw.category ?? \"\");\n if (!category) {\n invalidCategoryCount++;\n this.debugLog(\n `mnemo: smart-extractor: dropping candidate due to invalid category rawCategory=${JSON.stringify(raw.category ?? \"\")} abstract=${JSON.stringify((raw.abstract ?? \"\").trim().slice(0, 120))}`,\n );\n continue;\n }\n\n const abstract = (raw.abstract ?? \"\").trim();\n const overview = (raw.overview ?? \"\").trim();\n const content = (raw.content ?? \"\").trim();\n\n // Skip empty or noise\n if (!abstract || abstract.length < 5) {\n shortAbstractCount++;\n this.debugLog(\n `mnemo: smart-extractor: dropping candidate due to short abstract category=${category} abstract=${JSON.stringify(abstract)}`,\n );\n continue;\n }\n if (isNoise(abstract)) {\n noiseAbstractCount++;\n this.debugLog(\n `mnemo: smart-extractor: dropping candidate due to noise abstract category=${category} abstract=${JSON.stringify(abstract.slice(0, 120))}`,\n );\n continue;\n }\n\n candidates.push({ category, abstract, overview, content });\n }\n\n this.debugLog(\n `mnemo: smart-extractor: validation summary accepted=${candidates.length}, invalidCategory=${invalidCategoryCount}, shortAbstract=${shortAbstractCount}, noiseAbstract=${noiseAbstractCount}`,\n );\n\n return candidates;\n }\n\n // --------------------------------------------------------------------------\n // Step 2: Dedup + Persist\n // --------------------------------------------------------------------------\n\n /**\n * Process a single candidate memory: dedup \u2192 merge/create \u2192 store\n */\n private async processCandidate(\n candidate: CandidateMemory,\n sessionKey: string,\n stats: ExtractionStats,\n targetScope: string,\n scopeFilter: string[],\n ): Promise<void> {\n // Profile always merges (skip dedup)\n if (ALWAYS_MERGE_CATEGORIES.has(candidate.category)) {\n await this.handleProfileMerge(\n candidate,\n sessionKey,\n targetScope,\n scopeFilter,\n );\n stats.merged++;\n return;\n }\n\n // Embed the candidate for vector dedup\n const embeddingText = `${candidate.abstract} ${candidate.content}`;\n const vector = await this.embedder.embed(embeddingText);\n if (!vector || vector.length === 0) {\n this.log(\"memory-pro: smart-extractor: embedding failed, storing as-is\");\n await this.storeCandidate(candidate, vector || [], sessionKey, targetScope);\n stats.created++;\n return;\n }\n\n // Dedup pipeline\n const dedupResult = await this.deduplicate(candidate, vector, scopeFilter);\n\n switch (dedupResult.decision) {\n case \"create\":\n await this.storeCandidate(candidate, vector, sessionKey, targetScope);\n stats.created++;\n break;\n\n case \"merge\":\n if (\n dedupResult.matchId &&\n MERGE_SUPPORTED_CATEGORIES.has(candidate.category)\n ) {\n await this.handleMerge(\n candidate,\n dedupResult.matchId,\n scopeFilter,\n targetScope,\n dedupResult.contextLabel,\n );\n stats.merged++;\n } else {\n // Category doesn't support merge \u2192 create instead\n await this.storeCandidate(candidate, vector, sessionKey, targetScope);\n stats.created++;\n }\n break;\n\n case \"skip\":\n this.log(\n `memory-pro: smart-extractor: skipped [${candidate.category}] ${candidate.abstract.slice(0, 60)}`,\n );\n stats.skipped++;\n break;\n\n case \"support\":\n if (dedupResult.matchId) {\n await this.handleSupport(dedupResult.matchId, scopeFilter, { session: sessionKey, timestamp: Date.now() }, dedupResult.reason, dedupResult.contextLabel);\n stats.supported = (stats.supported ?? 0) + 1;\n } else {\n await this.storeCandidate(candidate, vector, sessionKey, targetScope);\n stats.created++;\n }\n break;\n\n case \"contextualize\":\n if (dedupResult.matchId) {\n await this.handleContextualize(candidate, vector, dedupResult.matchId, sessionKey, targetScope, scopeFilter, dedupResult.contextLabel);\n stats.created++;\n } else {\n await this.storeCandidate(candidate, vector, sessionKey, targetScope);\n stats.created++;\n }\n break;\n\n case \"contradict\":\n if (dedupResult.matchId) {\n await this.handleContradict(candidate, vector, dedupResult.matchId, sessionKey, targetScope, scopeFilter, dedupResult.contextLabel);\n stats.created++;\n } else {\n await this.storeCandidate(candidate, vector, sessionKey, targetScope);\n stats.created++;\n }\n break;\n }\n }\n\n // --------------------------------------------------------------------------\n // Dedup Pipeline (vector pre-filter + LLM decision)\n // --------------------------------------------------------------------------\n\n /**\n * Two-stage dedup: vector similarity search \u2192 LLM decision.\n */\n private async deduplicate(\n candidate: CandidateMemory,\n candidateVector: number[],\n scopeFilter: string[],\n ): Promise<DedupResult> {\n // Stage 1: Vector pre-filter \u2014 find similar memories\n const similar = await this.store.vectorSearch(\n candidateVector,\n 5,\n SIMILARITY_THRESHOLD,\n scopeFilter,\n );\n\n if (similar.length === 0) {\n return { decision: \"create\", reason: \"No similar memories found\" };\n }\n\n // Stage 2: LLM decision\n return this.llmDedupDecision(candidate, similar);\n }\n\n private async llmDedupDecision(\n candidate: CandidateMemory,\n similar: MemorySearchResult[],\n ): Promise<DedupResult> {\n const topSimilar = similar.slice(0, MAX_SIMILAR_FOR_PROMPT);\n const existingFormatted = topSimilar\n .map((r, i) => {\n // Extract L0 abstract from metadata if available, fallback to text\n let metaObj: Record<string, unknown> = {};\n try {\n metaObj = JSON.parse(r.entry.metadata || \"{}\");\n } catch { }\n const abstract = (metaObj.l0_abstract as string) || r.entry.text;\n const overview = (metaObj.l1_overview as string) || \"\";\n return `${i + 1}. [${(metaObj.memory_category as string) || r.entry.category}] ${abstract}\\n Overview: ${overview}\\n Score: ${r.score.toFixed(3)}`;\n })\n .join(\"\\n\");\n\n const prompt = buildDedupPrompt(\n candidate.abstract,\n candidate.overview,\n candidate.content,\n existingFormatted,\n );\n\n try {\n const data = await this.llm.completeJson<{\n decision: string;\n reason: string;\n match_index?: number;\n context_label?: string;\n }>(prompt, \"dedup-decision\");\n\n if (!data) {\n this.log(\n \"memory-pro: smart-extractor: dedup LLM returned unparseable response, defaulting to CREATE\",\n );\n return { decision: \"create\", reason: \"LLM response unparseable\" };\n }\n\n const decision = (data.decision?.toLowerCase() ??\n \"create\") as DedupDecision;\n if (!VALID_DECISIONS.has(decision)) {\n return {\n decision: \"create\",\n reason: `Unknown decision: ${data.decision}`,\n };\n }\n\n // Resolve merge target from LLM's match_index (1-based)\n const idx = data.match_index;\n const matchEntry =\n typeof idx === \"number\" && idx >= 1 && idx <= topSimilar.length\n ? topSimilar[idx - 1]\n : topSimilar[0];\n\n return {\n decision,\n reason: data.reason ?? \"\",\n matchId: [\"merge\", \"support\", \"contextualize\", \"contradict\"].includes(decision) ? matchEntry?.entry.id : undefined,\n contextLabel: typeof data.context_label === \"string\" ? data.context_label : undefined,\n };\n } catch (err) {\n this.log(\n `memory-pro: smart-extractor: dedup LLM failed: ${String(err)}`,\n );\n return { decision: \"create\", reason: `LLM failed: ${String(err)}` };\n }\n }\n\n // --------------------------------------------------------------------------\n // Merge Logic\n // --------------------------------------------------------------------------\n\n /**\n * Profile always-merge: read existing profile, merge with LLM, upsert.\n */\n private async handleProfileMerge(\n candidate: CandidateMemory,\n sessionKey: string,\n targetScope: string,\n scopeFilter: string[],\n ): Promise<void> {\n // Find existing profile memory by category\n const embeddingText = `${candidate.abstract} ${candidate.content}`;\n const vector = await this.embedder.embed(embeddingText);\n\n // Search for existing profile memories\n const existing = await this.store.vectorSearch(\n vector || [],\n 1,\n 0.3,\n scopeFilter,\n );\n const profileMatch = existing.find((r) => {\n try {\n const meta = JSON.parse(r.entry.metadata || \"{}\");\n return meta.memory_category === \"profile\";\n } catch {\n return false;\n }\n });\n\n if (profileMatch) {\n await this.handleMerge(\n candidate,\n profileMatch.entry.id,\n scopeFilter,\n targetScope,\n );\n } else {\n // No existing profile \u2014 create new\n await this.storeCandidate(candidate, vector || [], sessionKey, targetScope);\n }\n }\n\n /**\n * Merge a candidate into an existing memory using LLM.\n */\n private async handleMerge(\n candidate: CandidateMemory,\n matchId: string,\n scopeFilter: string[],\n targetScope: string,\n contextLabel?: string,\n ): Promise<void> {\n let existingAbstract = \"\";\n let existingOverview = \"\";\n let existingContent = \"\";\n\n try {\n const existing = await this.store.getById(matchId, scopeFilter);\n if (existing) {\n const meta = parseSmartMetadata(existing.metadata, existing);\n existingAbstract = meta.l0_abstract || existing.text;\n existingOverview = meta.l1_overview || \"\";\n existingContent = meta.l2_content || existing.text;\n }\n } catch {\n // Fallback: store as new\n this.log(\n `memory-pro: smart-extractor: could not read existing memory ${matchId}, storing as new`,\n );\n const vector = await this.embedder.embed(\n `${candidate.abstract} ${candidate.content}`,\n );\n await this.storeCandidate(\n candidate,\n vector || [],\n \"merge-fallback\",\n targetScope,\n );\n return;\n }\n\n // Call LLM to merge\n const prompt = buildMergePrompt(\n existingAbstract,\n existingOverview,\n existingContent,\n candidate.abstract,\n candidate.overview,\n candidate.content,\n candidate.category,\n );\n\n const merged = await this.llm.completeJson<{\n abstract: string;\n overview: string;\n content: string;\n }>(prompt, \"merge-memory\");\n\n if (!merged) {\n this.log(\"memory-pro: smart-extractor: merge LLM failed, skipping merge\");\n return;\n }\n\n // Re-embed the merged content\n const mergedText = `${merged.abstract} ${merged.content}`;\n const newVector = await this.embedder.embed(mergedText);\n\n // Update existing memory via store.update()\n const existing = await this.store.getById(matchId, scopeFilter);\n const metadata = stringifySmartMetadata(\n buildSmartMetadata(existing ?? { text: merged.abstract }, {\n l0_abstract: merged.abstract,\n l1_overview: merged.overview,\n l2_content: merged.content,\n memory_category: candidate.category,\n tier: \"working\",\n confidence: 0.8,\n }),\n );\n\n await this.store.update(\n matchId,\n {\n text: merged.abstract,\n vector: newVector,\n metadata,\n },\n scopeFilter,\n );\n\n // Update support stats on the merged memory\n try {\n const updatedEntry = await this.store.getById(matchId, scopeFilter);\n if (updatedEntry) {\n const meta = parseSmartMetadata(updatedEntry.metadata, updatedEntry);\n const supportInfo = parseSupportInfo(meta.support_info);\n const updated = updateSupportStats(supportInfo, contextLabel, \"support\");\n const finalMetadata = stringifySmartMetadata({ ...meta, support_info: updated });\n await this.store.update(matchId, { metadata: finalMetadata }, scopeFilter);\n }\n } catch {\n // Non-critical: merge succeeded, support stats update is best-effort\n }\n\n this.log(\n `memory-pro: smart-extractor: merged [${candidate.category}]${contextLabel ? ` [${contextLabel}]` : \"\"} into ${matchId.slice(0, 8)}`,\n );\n }\n\n // --------------------------------------------------------------------------\n // Context-Aware Handlers (support / contextualize / contradict)\n // --------------------------------------------------------------------------\n\n /**\n * Handle SUPPORT: update support stats on existing memory for a specific context.\n */\n private async handleSupport(\n matchId: string,\n scopeFilter: string[],\n source: { session: string; timestamp: number },\n reason: string,\n contextLabel?: string,\n ): Promise<void> {\n const existing = await this.store.getById(matchId, scopeFilter);\n if (!existing) return;\n\n const meta = parseSmartMetadata(existing.metadata, existing);\n const supportInfo = parseSupportInfo(meta.support_info);\n const updated = updateSupportStats(supportInfo, contextLabel, \"support\");\n meta.support_info = updated;\n\n await this.store.update(\n matchId,\n { metadata: stringifySmartMetadata(meta) },\n scopeFilter,\n );\n\n this.log(\n `memory-pro: smart-extractor: support [${contextLabel || \"general\"}] on ${matchId.slice(0, 8)} \u2014 ${reason}`,\n );\n }\n\n /**\n * Handle CONTEXTUALIZE: create a new entry that adds situational nuance,\n * linked to the original via a relation in metadata.\n */\n private async handleContextualize(\n candidate: CandidateMemory,\n vector: number[],\n matchId: string,\n sessionKey: string,\n targetScope: string,\n scopeFilter: string[],\n contextLabel?: string,\n ): Promise<void> {\n const storeCategory = this.mapToStoreCategory(candidate.category);\n const metadata = stringifySmartMetadata({\n l0_abstract: candidate.abstract,\n l1_overview: candidate.overview,\n l2_content: candidate.content,\n memory_category: candidate.category,\n tier: \"working\" as const,\n access_count: 0,\n confidence: 0.7,\n last_accessed_at: Date.now(),\n source_session: sessionKey,\n contexts: contextLabel ? [contextLabel] : [],\n relations: [{ type: \"contextualizes\", targetId: matchId }],\n });\n\n await this.store.store({\n text: candidate.abstract,\n vector,\n category: storeCategory,\n scope: targetScope,\n importance: this.getDefaultImportance(candidate.category),\n metadata,\n });\n\n this.log(\n `memory-pro: smart-extractor: contextualize [${contextLabel || \"general\"}] new entry linked to ${matchId.slice(0, 8)}`,\n );\n }\n\n /**\n * Handle CONTRADICT: create contradicting entry + record contradiction evidence\n * on the original memory's support stats.\n */\n private async handleContradict(\n candidate: CandidateMemory,\n vector: number[],\n matchId: string,\n sessionKey: string,\n targetScope: string,\n scopeFilter: string[],\n contextLabel?: string,\n ): Promise<void> {\n const now = Date.now();\n const nowIso = new Date(now).toISOString();\n\n // 1. Demote + expire the contradicted memory\n const existing = await this.store.getById(matchId, scopeFilter);\n if (existing) {\n const meta = parseSmartMetadata(existing.metadata, existing);\n const supportInfo = parseSupportInfo(meta.support_info);\n const updated = updateSupportStats(supportInfo, contextLabel, \"contradict\");\n meta.support_info = updated;\n meta.expired_at = nowIso;\n meta.expired_reason = `contradicted by: ${candidate.abstract.slice(0, 120)}`;\n meta.superseded_by_session = sessionKey;\n await this.store.update(\n matchId,\n {\n importance: Math.max(0.05, (existing.importance ?? 0.7) * 0.2),\n metadata: stringifySmartMetadata(meta),\n },\n scopeFilter,\n );\n\n // 2. Expire in Graphiti (fire-and-forget)\n if (process.env.GRAPHITI_ENABLED === \"true\") {\n const graphitiBase = process.env.GRAPHITI_BASE_URL || \"http://127.0.0.1:18799\";\n fetch(`${graphitiBase}/facts/expire`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n text: existing.text,\n expired_at: nowIso,\n reason: `contradicted: ${candidate.abstract.slice(0, 80)}`,\n }),\n signal: AbortSignal.timeout(5000),\n }).catch(() => {});\n }\n\n this.log(\n `memory-pro: smart-extractor: expired old memory ${matchId.slice(0, 8)} (imp ${(existing.importance ?? 0.7).toFixed(2)}\u2192${Math.max(0.05, (existing.importance ?? 0.7) * 0.2).toFixed(2)})`,\n );\n }\n\n // 3. Store the new (contradicting) entry with supersedes relation\n const storeCategory = this.mapToStoreCategory(candidate.category);\n const metadata = stringifySmartMetadata({\n l0_abstract: candidate.abstract,\n l1_overview: candidate.overview,\n l2_content: candidate.content,\n memory_category: candidate.category,\n tier: \"working\" as const,\n access_count: 0,\n confidence: 0.85,\n last_accessed_at: now,\n source_session: sessionKey,\n contexts: contextLabel ? [contextLabel] : [],\n relations: [\n { type: \"contradicts\", targetId: matchId },\n { type: \"supersedes\", targetId: matchId },\n ],\n valid_from: nowIso,\n });\n\n await this.store.store({\n text: candidate.abstract,\n vector,\n category: storeCategory,\n scope: targetScope,\n importance: Math.min(1.0, this.getDefaultImportance(candidate.category) + 0.1),\n metadata,\n });\n\n this.log(\n `memory-pro: smart-extractor: contradict [${contextLabel || \"general\"}] superseded ${matchId.slice(0, 8)} \u2192 new entry (imp ${(this.getDefaultImportance(candidate.category) + 0.1).toFixed(2)})`,\n );\n }\n\n // --------------------------------------------------------------------------\n // Store Helper\n // --------------------------------------------------------------------------\n\n /**\n * Store a candidate memory as a new entry with L0/L1/L2 metadata.\n */\n private async storeCandidate(\n candidate: CandidateMemory,\n vector: number[],\n sessionKey: string,\n targetScope: string,\n ): Promise<void> {\n // Map 6-category to existing store categories for backward compatibility\n const storeCategory = this.mapToStoreCategory(candidate.category);\n\n const metadata = stringifySmartMetadata(\n buildSmartMetadata(\n {\n text: candidate.abstract,\n category: this.mapToStoreCategory(candidate.category),\n },\n {\n l0_abstract: candidate.abstract,\n l1_overview: candidate.overview,\n l2_content: candidate.content,\n memory_category: candidate.category,\n tier: \"working\",\n access_count: 0,\n confidence: 0.7,\n source_session: sessionKey,\n },\n ),\n );\n\n await this.store.store({\n text: candidate.abstract, // L0 used as the searchable text\n vector,\n category: storeCategory,\n scope: targetScope,\n importance: this.getDefaultImportance(candidate.category),\n metadata,\n });\n\n this.log(\n `memory-pro: smart-extractor: created [${candidate.category}] ${candidate.abstract.slice(0, 60)}`,\n );\n }\n\n /**\n * Map 6-category to existing 5-category store type for backward compatibility.\n */\n private mapToStoreCategory(\n category: MemoryCategory,\n ): \"preference\" | \"fact\" | \"decision\" | \"entity\" | \"other\" {\n switch (category) {\n case \"profile\":\n return \"fact\";\n case \"preferences\":\n return \"preference\";\n case \"entities\":\n return \"entity\";\n case \"events\":\n return \"decision\";\n case \"cases\":\n return \"fact\";\n case \"patterns\":\n return \"other\";\n default:\n return \"other\";\n }\n }\n\n /**\n * Get default importance score by category.\n */\n private getDefaultImportance(category: MemoryCategory): number {\n switch (category) {\n case \"profile\":\n return 0.9; // Identity is very important\n case \"preferences\":\n return 0.8;\n case \"entities\":\n return 0.7;\n case \"events\":\n return 0.6;\n case \"cases\":\n return 0.8; // Problem-solution pairs are high value\n case \"patterns\":\n return 0.85; // Reusable processes are high value\n default:\n return 0.5;\n }\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["existing"]
7
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"smart-metadata.d.ts","sourceRoot":"","sources":["../../src/smart-metadata.ts"],"names":[],"mappings":"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"}