Skip to content

Types

All types are exported from vitamem and are available as TypeScript types.

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;
}
type ThreadState = "active" | "cooling" | "dormant" | "closed";
interface Message {
id: string;
threadId: string;
role: "user" | "assistant" | "system";
content: string;
createdAt: Date;
}

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;
}
FieldTypeDescription
idstringUnique identifier
userIdstringOwner user ID
threadIdstringThread that produced this memory
contentstringThe fact text
sourceMemorySource"confirmed" (user stated) or "inferred" (derived)
embeddingnumber[] | nullEmbedding vector for similarity search
createdAtDateWhen the memory was created
pinnedboolean?Whether this memory is pinned (always retrieved, exempt from decay)
tagsstring[]?Optional tags for filtering
lastRetrievedAtDate?When this memory was last retrieved for context injection
retrievalCountnumber?How many times this memory has been retrieved

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;
}
type MemorySource = "confirmed" | "inferred";

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[]>;
}

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.


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.


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;
}
FieldTypeDefaultDescription
forgettingHalfLifeMsnumber15552000000 (180 days)Time in ms until unretrieved memory relevance halves
minRetrievalScorenumber0.1Score threshold below which memories become archival candidates

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';
}>;
}
FieldTypeDescription
correctedFactsArrayAll original facts annotated with action: "keep" (correct), "enrich" (improved), or "remove" (wrong/useless)
missedFactsArrayImportant facts from the conversation that were not extracted in the first pass
conflictsArrayCases where a new fact directly contradicts an existing memory, with a resolution strategy

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;
}
FieldTypeDescription
userIdstringOwner user ID
conditionsstring[]Active medical conditions
medicationsMedication[]Current medications with dosage info
allergiesstring[]Known allergies
vitalsRecord<string, VitalRecord>Health vitals keyed by metric name (e.g., "a1c", "blood_pressure", "weight")
goalsstring[]Health and wellness goals
emergencyContactsstring[]Emergency contacts
customFieldsRecord<string, unknown>Extensible key-value store for domain-specific fields
updatedAtDate?Last time profile was updated
interface Medication {
name: string;
dosage?: string;
frequency?: string;
/** When the medication was started or last confirmed */
updatedAt?: Date;
}
interface VitalRecord {
value: number;
unit: string;
/** When this reading was recorded */
recordedAt?: Date;
/** Previous value before this update, for tracking trends */
previousValue?: number;
}

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;
}

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).

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 result for a new fact against existing memories.

type FactClassification =
| { action: "skip" }
| { action: "supersede"; existingIndex: number; similarity: number }
| { action: "save" };
ActionConditionDescription
"skip"similarity >= deduplicationThresholdExact duplicate, discard
"supersede"similarity >= supersedeThreshold and < deduplicationThresholdSame topic with updated value, update existing memory
"save"similarity < supersedeThresholdNew distinct fact, save as new memory

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>;
}

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";

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";

Create an empty UserProfile with default empty arrays and objects.

import { createEmptyProfile } from "vitamem";
const profile = createEmptyProfile("user-123");