Types
All types are exported from vitamem and are available as TypeScript types.
Core Types
Section titled “Core Types”Thread
Section titled “Thread”Represents a conversation thread and its lifecycle state.
interface Thread { id: string; userId: string; state: ThreadState; // 'active' | 'cooling' | 'dormant' | 'closed' messages: Message[]; createdAt: Date; updatedAt: Date; lastMessageAt: Date | null; coolingStartedAt: Date | null; dormantAt: Date | null; closedAt: Date | null;}ThreadState
Section titled “ThreadState”type ThreadState = "active" | "cooling" | "dormant" | "closed";Message
Section titled “Message”interface Message { id: string; threadId: string; role: "user" | "assistant" | "system"; content: string; createdAt: Date;}Memory
Section titled “Memory”A stored fact about a user, with its embedding vector.
interface Memory { id: string; userId: string; threadId: string; content: string; source: MemorySource; // 'confirmed' | 'inferred' embedding: number[] | null; createdAt: Date; pinned?: boolean; tags?: string[]; /** When this memory was last retrieved for context injection */ lastRetrievedAt?: Date; /** How many times this memory has been retrieved */ retrievalCount?: number;}| Field | Type | Description |
|---|---|---|
id | string | Unique identifier |
userId | string | Owner user ID |
threadId | string | Thread that produced this memory |
content | string | The fact text |
source | MemorySource | "confirmed" (user stated) or "inferred" (derived) |
embedding | number[] | null | Embedding vector for similarity search |
createdAt | Date | When the memory was created |
pinned | boolean? | Whether this memory is pinned (always retrieved, exempt from decay) |
tags | string[]? | Optional tags for filtering |
lastRetrievedAt | Date? | When this memory was last retrieved for context injection |
retrievalCount | number? | How many times this memory has been retrieved |
MemoryMatch
Section titled “MemoryMatch”A memory returned from retrieve(), including its similarity score.
interface MemoryMatch { content: string; source: MemorySource; score: number; // 0–1 cosine similarity id?: string; createdAt?: Date; pinned?: boolean; tags?: string[]; embedding?: number[]; /** When this memory was last retrieved */ lastRetrievedAt?: Date; /** How many times this memory has been retrieved */ retrievalCount?: number;}MemorySource
Section titled “MemorySource”type MemorySource = "confirmed" | "inferred";Adapter Interfaces
Section titled “Adapter Interfaces”LLMAdapter
Section titled “LLMAdapter”interface LLMAdapter { chat(messages: Array<{ role: string; content: string }>): Promise<string>; chatStream?( messages: Array<{ role: string; content: string }>, ): AsyncGenerator<string, void, unknown>; extractMemories( messages: Message[], sessionDate?: string, ): Promise<Array<{ content: string; source: MemorySource; tags?: string[]; profileField?: 'conditions' | 'medications' | 'allergies' | 'vitals' | 'goals' | 'none'; profileKey?: string; profileValue?: string | number | { name: string; dosage?: string; frequency?: string }; profileUnit?: string; }>>; embed(text: string): Promise<number[]>;}StorageAdapter
Section titled “StorageAdapter”The full interface includes optional methods for lifecycle sweeps, pinning, profiles, and GDPR deletion:
interface StorageAdapter { createThread(userId: string): Promise<Thread>; getThread(threadId: string): Promise<Thread | null>; getThreadsByState?(state: ThreadState): Promise<Thread[]>; updateThread(thread: Thread): Promise<Thread>; addMessage(threadId: string, role: Message["role"], content: string): Promise<Message>; getMessages(threadId: string): Promise<Message[]>; saveMemory(memory: Omit<Memory, "id" | "createdAt">): Promise<Memory>; getMemories(userId: string): Promise<Memory[]>; searchMemories( userId: string, embedding: number[], limit?: number, filterTags?: string[], ): Promise<MemoryMatch[]>; deleteMemory?(memoryId: string): Promise<void>; deleteUserMemories?(userId: string): Promise<void>; getLatestActiveThread?(userId: string): Promise<Thread | null>; getPinnedMemories?(userId: string): Promise<Memory[]>; updateMemory?(memoryId: string, updates: Partial<Memory>): Promise<void>; getProfile?(userId: string): Promise<UserProfile | null>; updateProfile?(userId: string, updates: Partial<Omit<UserProfile, "userId">>): Promise<void>; updateProfileField?(userId: string, field: string, value: unknown, action: "set" | "add" | "remove"): Promise<void>;}See the full Storage Adapter reference for details on each method.
Configuration
Section titled “Configuration”VitamemConfig
Section titled “VitamemConfig”The unified config object passed to createVitamem(). Provide either a provider string or an llm adapter instance.
type ProviderName = "openai" | "anthropic" | "ollama";
interface VitamemConfig { // LLM — string shortcut OR adapter instance (one required) provider?: ProviderName; apiKey?: string; model?: string; extractionModel?: string; embeddingModel?: string; baseUrl?: string; llm?: LLMAdapter;
// Storage — string shortcut OR adapter instance (required) storage: "ephemeral" | "supabase" | StorageAdapter; supabaseUrl?: string; supabaseKey?: string;
// OpenAI-specific API mode and pass-through options apiMode?: 'completions' | 'responses'; extraChatOptions?: Record<string, unknown>; extraEmbeddingOptions?: Record<string, unknown>;
// Behavioral settings preset?: PresetName; coolingTimeoutMs?: number; // default: 6 hours (21600000) dormantTimeoutMs?: number; // default: coolingTimeoutMs closedTimeoutMs?: number; // default: 30 days (2592000000) embeddingConcurrency?: number; // default: 5 autoRetrieve?: boolean; // default: false
// Retrieval controls onRetrieve?: (memories: MemoryMatch[], query: string) => MemoryMatch[] | Promise<MemoryMatch[]>; minScore?: number; // default: 0 recencyWeight?: number; // 0-1, default: 0 recencyMaxAgeMs?: number; // default: 90 days diversityWeight?: number; // 0-1, default: 0
// Memory Extraction extractionPrompt?: string; memoryContextFormatter?: (memories: MemoryMatch[], query: string) => string;
// Deduplication & Supersede deduplicationThreshold?: number; // default: 0.92 supersedeThreshold?: number; // default: 0.75
// Active Forgetting forgetting?: ForgettingConfig;
// Auto-Pinning autoPinRules?: AutoPinRule[];
// Structured Extraction structuredExtractionRules?: StructuredExtractionRule[];
// Extraction Reflection enableReflection?: boolean; // default: false reflectionPrompt?: string;
// Formatter Overhaul cacheableContext?: boolean; // default: false prioritySignaling?: boolean; // default: true chronologicalRetrieval?: boolean; // default: true}See createVitamem for full details on each option.
Forgetting & Decay
Section titled “Forgetting & Decay”ForgettingConfig
Section titled “ForgettingConfig”Configuration for the active forgetting / relevance decay system.
interface ForgettingConfig { /** Half-life for memory decay in milliseconds. Default: 180 days (15552000000ms) */ forgettingHalfLifeMs?: number; /** Score threshold below which memories are archived. Default: 0.1 */ minRetrievalScore?: number;}| Field | Type | Default | Description |
|---|---|---|---|
forgettingHalfLifeMs | number | 15552000000 (180 days) | Time in ms until unretrieved memory relevance halves |
minRetrievalScore | number | 0.1 | Score threshold below which memories become archival candidates |
Reflection
Section titled “Reflection”ReflectionResult
Section titled “ReflectionResult”Result of the extraction reflection pass. Returned by reflectOnExtraction().
interface ReflectionResult { correctedFacts: Array<{ content: string; source: 'confirmed' | 'inferred'; action: 'keep' | 'enrich' | 'remove'; reason?: string; tags?: string[]; profileField?: string; profileKey?: string; profileValue?: string; profileUnit?: string; }>; missedFacts: Array<{ content: string; source: 'confirmed' | 'inferred'; tags?: string[]; profileField?: string; profileKey?: string; profileValue?: string; profileUnit?: string; }>; conflicts: Array<{ newFact: string; existingMemory: string; resolution: 'keep_new' | 'keep_existing' | 'merge'; }>;}| Field | Type | Description |
|---|---|---|
correctedFacts | Array | All original facts annotated with action: "keep" (correct), "enrich" (improved), or "remove" (wrong/useless) |
missedFacts | Array | Important facts from the conversation that were not extracted in the first pass |
conflicts | Array | Cases where a new fact directly contradicts an existing memory, with a resolution strategy |
Structured Profile Types
Section titled “Structured Profile Types”UserProfile
Section titled “UserProfile”Structured user profile for hybrid memory. Automatically populated from extracted facts when structuredExtractionRules are configured.
interface UserProfile { userId: string; /** Active medical conditions */ conditions: string[]; /** Current medications with dosage information */ medications: Medication[]; /** Known allergies */ allergies: string[]; /** Health vitals keyed by metric name (e.g., "a1c", "blood_pressure", "weight") */ vitals: Record<string, VitalRecord>; /** Health and wellness goals */ goals: string[]; /** Emergency contacts */ emergencyContacts: string[]; /** Extensible key-value store for domain-specific fields */ customFields: Record<string, unknown>; /** Last time profile was updated */ updatedAt?: Date;}| Field | Type | Description |
|---|---|---|
userId | string | Owner user ID |
conditions | string[] | Active medical conditions |
medications | Medication[] | Current medications with dosage info |
allergies | string[] | Known allergies |
vitals | Record<string, VitalRecord> | Health vitals keyed by metric name (e.g., "a1c", "blood_pressure", "weight") |
goals | string[] | Health and wellness goals |
emergencyContacts | string[] | Emergency contacts |
customFields | Record<string, unknown> | Extensible key-value store for domain-specific fields |
updatedAt | Date? | Last time profile was updated |
Medication
Section titled “Medication”interface Medication { name: string; dosage?: string; frequency?: string; /** When the medication was started or last confirmed */ updatedAt?: Date;}VitalRecord
Section titled “VitalRecord”interface VitalRecord { value: number; unit: string; /** When this reading was recorded */ recordedAt?: Date; /** Previous value before this update, for tracking trends */ previousValue?: number;}StructuredFact
Section titled “StructuredFact”An intermediate type representing a fact classified against the user profile schema.
interface StructuredFact { /** Which profile field this fact maps to */ field: keyof Omit<UserProfile, "userId" | "customFields" | "updatedAt">; /** The extracted value (type depends on field) */ value: unknown; /** Whether to set, add to array, or remove from array */ action: "set" | "add" | "remove"; /** Original extracted text that produced this fact */ sourceText: string;}Auto-Pin & Extraction Rules
Section titled “Auto-Pin & Extraction Rules”AutoPinRule
Section titled “AutoPinRule”Rule for automatically pinning critical memories during extraction. Can be a regex pattern match or a custom test function.
type AutoPinRule = | { pattern: RegExp; reason?: string } | { test: (memory: { content: string; source: MemorySource; tags?: string[] }) => boolean; reason?: string };Use the built-in HEALTH_AUTO_PIN_RULES constant for health domain auto-pinning (allergies, anaphylaxis, drug interactions, contraindications, emergency contacts, blood type, medication dosages).
StructuredExtractionRule
Section titled “StructuredExtractionRule”Rule for classifying extracted facts into structured profile fields using regex pattern matching.
interface StructuredExtractionRule { /** Regex pattern to match against extracted fact text */ pattern: RegExp; /** Which profile field this rule targets */ profileField: keyof Omit<UserProfile, "userId" | "customFields" | "updatedAt">; /** Function to extract the structured value from the matched text */ extractor: (text: string, match: RegExpMatchArray) => { value: unknown; action: "set" | "add" | "remove"; };}Use the built-in HEALTH_STRUCTURED_RULES constant for health domain structured extraction (vitals, allergies, medications, conditions, goals).
Classification Types
Section titled “Classification Types”FactClassification
Section titled “FactClassification”Classification result for a new fact against existing memories.
type FactClassification = | { action: "skip" } | { action: "supersede"; existingIndex: number; similarity: number } | { action: "save" };| Action | Condition | Description |
|---|---|---|
"skip" | similarity >= deduplicationThreshold | Exact duplicate, discard |
"supersede" | similarity >= supersedeThreshold and < deduplicationThreshold | Same topic with updated value, update existing memory |
"save" | similarity < supersedeThreshold | New distinct fact, save as new memory |
Facade Interface
Section titled “Facade Interface”Vitamem
Section titled “Vitamem”The object returned by createVitamem().
interface Vitamem { createThread(opts: { userId: string }): Promise<Thread>; chat(opts: { threadId: string; message: string; systemPrompt?: string; }): Promise<{ reply: string; thread: Thread; memories?: MemoryMatch[]; previousThreadId?: string; redirected?: boolean; }>; chatStream(opts: { threadId: string; message: string; systemPrompt?: string; }): Promise<{ stream: AsyncGenerator<string, void, unknown>; thread: Thread; memories?: MemoryMatch[]; previousThreadId?: string; redirected?: boolean; }>; retrieve(opts: { userId: string; query: string; limit?: number; filterTags?: string[]; }): Promise<MemoryMatch[]>; pinMemory(memoryId: string): Promise<void>; unpinMemory(memoryId: string): Promise<void>; getThread(threadId: string): Promise<Thread | null>; getOrCreateThread(userId: string): Promise<Thread>; chatWithUser(opts: { userId: string; message: string; systemPrompt?: string; }): Promise<{ reply: string; thread: Thread; memories?: MemoryMatch[]; previousThreadId?: string; redirected?: boolean }>; chatWithUserStream(opts: { userId: string; message: string; systemPrompt?: string; }): Promise<{ stream: AsyncGenerator<string>; thread: Thread; memories?: MemoryMatch[]; previousThreadId?: string; redirected?: boolean }>; triggerDormantTransition(threadId: string): Promise<{ memoriesSaved: number; memoriesDeduped: number; memoriesSuperseded: number; totalExtracted: number; profileFieldsUpdated: number; }>; closeThread(threadId: string): Promise<void>; sweepThreads(): Promise<void>; deleteMemory(memoryId: string): Promise<void>; deleteUserData(userId: string): Promise<void>; getProfile(userId: string): Promise<UserProfile | null>; updateProfile(userId: string, updates: Partial<Omit<UserProfile, "userId">>): Promise<void>;}Constants
Section titled “Constants”HEALTH_AUTO_PIN_RULES
Section titled “HEALTH_AUTO_PIN_RULES”Built-in auto-pin rules for health companion use cases. Automatically pins memories containing critical safety information (allergies, anaphylaxis, drug interactions, contraindications, emergency contacts, blood type, medication dosages).
import { HEALTH_AUTO_PIN_RULES } from "vitamem";HEALTH_STRUCTURED_RULES
Section titled “HEALTH_STRUCTURED_RULES”Built-in structured extraction rules for health domains. Matches vitals (A1C, blood pressure, weight, blood glucose), allergies, medications, conditions, and goals.
import { HEALTH_STRUCTURED_RULES } from "vitamem";createEmptyProfile(userId)
Section titled “createEmptyProfile(userId)”Create an empty UserProfile with default empty arrays and objects.
import { createEmptyProfile } from "vitamem";
const profile = createEmptyProfile("user-123");