Skip to content

MemoryLtmService

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:78

new MemoryLtmService(prisma, stmService?, embeddingsService?, vectorStore?, importanceService?, duplicateDetectionService?, ingestPipeline?, contradictionDetectionService?): MemoryLtmService

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:82

PrismaService

PostgresStmAdapter

EmbeddingsService

VectorStore

ImportanceScoringService

DuplicateDetectionService

IngestPipelineService

ContradictionDetectionService

MemoryLtmService

applyDecayPolicy(options?): Promise<DecayPolicyResult>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:1282

DecayPolicyOptions = {}

Promise<DecayPolicyResult>


casMetadataUpdate(memoryId, userId, organizationId, expectedVersion, data, options?): Promise<PrismaMemory | null>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:1815

Compare-and-swap metadata write for internal lifecycle paths (G3-T3).

Mirrors the user-facing update()’s CAS semantics exactly — same where shape (id + userId + type, plus organizationId when supplied) with the expected version folded in, and a version: { increment: 1 } — so lifecycle writes participate in the SAME optimistic-concurrency protocol as user edits instead of silently clobbering them.

options.bumpVersion: false keeps the version-KEYED where (a stale write still can never clobber a concurrent edit — it just misses) but skips the increment. Used ONLY by the access-bookkeeping hot path: get() and recall() record accesses, so an access write that bumped version would invalidate the version the caller just read and every read-then-update flow using expectedVersion (G4-T2) would 409 against its own access bump.

Returns null when the CAS missed (version moved or row gone — Prisma P2025); callers decide whether to re-read + retry once or skip. Non-P2025 errors are rethrown unchanged.

Public-but-internal: exposed (not private) ONLY so CorpusConsolidationService (G3-T2) can route its supersede/tag-union writes through the exact same G3-T3 CAS protocol instead of duplicating it. Not part of the app-facing API — application code must use update().

string

string

string | null | undefined

number

Record<string, unknown>

boolean

Promise<PrismaMemory | null>


clear(userId): Promise<number>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:838

Clear all long-term memories for a user

string

Promise<number>


count(userId, filters?): Promise<number>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:782

Count total long-term memories for a user

string

Partial<LtmQueryOptions>

Promise<number>


create(input): Promise<LtmMemory>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:109

Create a new long-term memory.

Runs the B0 ingest pipeline (steps 1–6) before write, then handles steps 7 (PostgresWrite), 11 (EmbeddingGenerate), and 12 (SearchIndexUpdate) inline. Steps 8–10 and 13 fire asynchronously after a successful write.

CreateLtmMemoryData

Promise<LtmMemory>


delete(userId, memoryId, organizationId?, scope?): Promise<boolean>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:639

Delete a long-term memory. Pass organizationId in user-facing paths to prevent cross-tenant deletes. See get() for the full isolation contract.

string

string

string

string

Promise<boolean>


findInsightCandidates(topic, limit, userId?): Promise<LtmMemory[]>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:1266

Return LTM memories that carry a given topic tag and have not yet been clustered (i.e. not tagged insight or clustered). Used by the insight extraction job. The clustered tag is written atomically with the insightId metadata field in the same update call, so filtering by tag is sufficient to exclude already-processed memories.

string

number

string

Promise<LtmMemory[]>


get(userId, memoryId, organizationId?, scope?): Promise<LtmMemory | null>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:319

Retrieve a long-term memory by ID.

When organizationId is provided the query is narrowed to that org’s rows, preventing cross-tenant access. Omitting it is permitted for admin / system callers (e.g. reindex) but must NOT be used in user-facing paths — the auth layer (#128, #130) must always supply the caller’s org context.

string

string

string

string

Promise<LtmMemory | null>


list(userId, options?): Promise<PaginatedResult<LtmMemory>>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:682

List long-term memories for a user with pagination and filtering

string

LtmQueryOptions

Promise<PaginatedResult<LtmMemory>>


promote(userId, memoryId, organizationId?, scope?): Promise<LtmMemory>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:862

Promote a memory from short-term to long-term storage. Pass organizationId and scope to preserve both namespaces through the STM→LTM transfer.

string

string

string

string

Promise<LtmMemory>


recordLifecycleAudit(entry): Promise<void>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:1905

Append a lifecycle mutation to the memory_audits trail (G3-T3).

Same column shape as the mcp-server MemoryAuditService.record() write (WP2 T5) — action delete rows here are picked up unchanged by findLatestDeleteSnapshot() / restore_memory — but attributed to a system actor (actorType: 'system', actorId naming the job) because no verified API-key principal exists inside a background job. Best-effort: NEVER throws — a lost audit row must not fail the lifecycle mutation that already happened.

Public-but-internal (same rationale as casMetadataUpdate): shared with CorpusConsolidationService (G3-T2, actor corpus_consolidation) so there is exactly ONE lifecycle-audit writer.

"supersede" | "delete"

"ltm_decay" | "dedup_supersede" | "corpus_consolidation"

Record<string, unknown>

Record<string, unknown>

string

string | null

string | null

string

Promise<void>


recreateVectorIndex(): Promise<void>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:1551

Drop and rebuild the vector index from scratch. Destructive and NOT atomic: recall returns empty for all tenants until a subsequent reindex backfills the index. Callers that chunk their own backfill (e.g. the async reindex queue) invoke this exactly once up front, then reindex batch-by-batch with recreate: false — the per-batch recreate guard in reindex would otherwise skip the rebuild because every chunked call passes maxMemories. No-op (with a warning) when no vector store is configured.

Promise<void>


reembed(userId, memoryId, organizationId?, scope?): Promise<LtmMemory>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:524

Regenerate the embedding for a memory’s CURRENT content and re-index it, clearing metadata.embeddingStale (WP2 T7/D10). Repairs a memory whose content was edited during an embeddings outage.

Deliberately does NOT bump version: re-sending identical content through update() would trip the T4 compare-and-swap for other writers. updatedAt is allowed to move. Throws LtmEmbeddingUnavailableError when no embedding can be produced, leaving the staleness flag in place for a later retry.

string

string

string

string

Promise<LtmMemory>


reindex(options?): Promise<ReindexResult>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:1570

Backfill / reindex the vector store from Postgres.

Pages through long-term memories using a stable cursor, (re)generates embeddings as needed, and upserts them into the configured vector store. The operation is idempotent and cursor-resumable: re-running it is safe and picks up where a prior run stopped when a cursor is supplied. Postgres remains the source of truth, so per-item failures are counted and skipped rather than aborting the whole run.

ReindexOptions = {}

Promise<ReindexResult>


restore(input): Promise<LtmMemory>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:584

Recreate a long-term memory from a delete snapshot, preserving its ORIGINAL id so id-keyed vector upserts and inbound links stay valid (WP2 T5/G5). Runs through the same quota-guarded insert path as create, re-embeds the content, and re-indexes the vector. Fails with LtmMemoryQuotaExceededError if the user is at quota, and is a no-op-safe recreate: if the id already exists the Prisma insert throws and surfaces as a database error.

string

string

Record<string, unknown> | null

string | null

string | null

string[]

string

Promise<LtmMemory>


semanticSearch(userId, query, options?): Promise<SemanticSearchResult[]>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:1146

Perform a semantic (vector) recall over a user’s long-term memories.

Embeds the query, runs a tenant-scoped kNN search in the vector store, then hydrates the matching memories from Postgres and attaches similarity scores. Returns an empty array when embeddings or the vector store are unavailable.

string

string

SemanticSearchOptions

Promise<SemanticSearchResult[]>


update(userId, memoryId, input, organizationId?, scope?): Promise<LtmMemory>

Defined in: packages/memory-ltm/src/memory-ltm.service.ts:359

Update a long-term memory. Pass organizationId in user-facing paths to prevent cross-tenant writes. See get() for the full isolation contract.

string

string

UpdateLtmMemoryData

string

string

Promise<LtmMemory>