import { z } from 'zod'; import OpenAI from 'openai'; /** * Input message format — matches the OpenAI/Anthropic message shape. */ declare const MessageSchema: z.ZodObject<{ role: z.ZodEnum<["user", "assistant", "system", "tool"]>; content: z.ZodString; }, "strip", z.ZodTypeAny, { role: "user" | "assistant" | "system" | "tool"; content: string; }, { role: "user" | "assistant" | "system" | "tool"; content: string; }>; type Message = z.infer; declare const MessagesSchema: z.ZodArray; content: z.ZodString; }, "strip", z.ZodTypeAny, { role: "user" | "assistant" | "system" | "tool"; content: string; }, { role: "user" | "assistant" | "system" | "tool"; content: string; }>, "many">; /** * A stored memory fact. */ interface Memory { id: string; /** The extracted fact, in plain English. */ content: string; /** Vector embedding of the content. */ embedding: number[]; userId?: string; agentId?: string; sessionId?: string; metadata: Record; createdAt: Date; updatedAt: Date; } /** * Result from {@link TurboMemory.search}. */ interface MemorySearchResult { memory: Memory; /** Cosine similarity score, 0–1. */ score: number; } /** * Scope for operations — provide at least one of userId or agentId. */ interface MemoryScope { userId?: string; agentId?: string; sessionId?: string; } declare const MemoryScopeSchema: z.ZodObject<{ userId: z.ZodOptional; agentId: z.ZodOptional; sessionId: z.ZodOptional; }, "strip", z.ZodTypeAny, { userId?: string | undefined; agentId?: string | undefined; sessionId?: string | undefined; }, { userId?: string | undefined; agentId?: string | undefined; sessionId?: string | undefined; }>; /** * Pluggable embedding backend. */ interface EmbeddingAdapter { embed(text: string): Promise; embedBatch(texts: string[]): Promise; readonly dimensions: number; } /** * Pluggable storage backend. */ interface StorageAdapter { /** * Initialise the store. Receives the embedding dimensions so the underlying * vector column can be created with a matching size. */ init(dimensions: number): Promise; insert(memory: Omit): Promise; update(id: string, patch: { content: string; embedding: number[]; metadata?: Record; }): Promise; search(embedding: number[], scope: MemoryScope, limit: number): Promise; getAll(scope: MemoryScope): Promise; delete(id: string): Promise; deleteAll(scope: MemoryScope): Promise; /** Release any held resources (file handles, db connections). */ close?(): Promise; } /** Supported providers for LLM-based fact extraction. */ type ExtractionProvider = "openai" | "anthropic" | "google"; interface ExtractionConfig { provider: ExtractionProvider; model: string; apiKey?: string; baseURL?: string; } interface OpenAIConfig { apiKey?: string; baseURL?: string; } /** Options for the Voyage embedding adapter. */ interface VoyageConfig { apiKey?: string; baseURL?: string; model?: string; dimensions?: number; } /** Options for the Google (Gemini) embedding adapter. */ interface GoogleConfig { apiKey?: string; baseURL?: string; model?: string; dimensions?: number; } /** How overlapping memories are handled on write. */ type DeduplicationStrategy = "replace" | "skip" | "merge"; /** Controls semantic deduplication during {@link TurboMemory.add} / {@link TurboMemory.addFacts}. */ interface DeduplicationConfig { /** Default true. Set false to always insert new rows. */ enabled?: boolean; /** Cosine similarity threshold (0–1). Default 0.92. */ threshold?: number; /** Default "merge". */ strategy?: DeduplicationStrategy; /** Max similar memories to retrieve for merge / consolidation. Default 5. */ mergeTopK?: number; } /** * Configuration for the {@link TurboMemory} class. */ interface TurboMemoryConfig { embeddings: "openai" | "local" | "voyage" | "google" | EmbeddingAdapter; storage?: "pglite" | "sqlite-vec" | "upstash-vector" | "pinecone" | StorageAdapter; extraction: ExtractionConfig; openai?: OpenAIConfig; /** Options forwarded to the Voyage embedding adapter. */ voyage?: VoyageConfig; /** Options forwarded to the Google embedding adapter. */ google?: GoogleConfig; pglite?: { /** * Persistence location. Defaults to `.turbomem` in `process.cwd()` on Node, * or `idb://turbomem` in the browser. Prefix with `idb://` for IndexedDB. */ dataDir?: string; /** Use an in-memory database (ignores `dataDir`). Handy for tests. */ inMemory?: boolean; /** * When true, PGlite returns before IndexedDB flushes complete. Defaults to * `true` for `idb://` paths. */ relaxedDurability?: boolean; }; sqliteVec?: { /** Defaults to `.turbomem.sqlite` in `process.cwd()`. */ dbPath?: string; /** Use an in-memory database. Handy for tests. */ inMemory?: boolean; }; upstashVector?: { /** Upstash Vector REST URL. Falls back to `UPSTASH_VECTOR_REST_URL`. */ url?: string; /** Upstash Vector REST token. Falls back to `UPSTASH_VECTOR_REST_TOKEN`. */ token?: string; /** Optional Upstash namespace. */ namespace?: string; }; pinecone?: { /** Pinecone API key. Falls back to `PINECONE_API_KEY`. */ apiKey?: string; /** Pinecone index name. Falls back to `PINECONE_INDEX`. */ index?: string; /** Direct index host (skips `describeIndex` lookup). Falls back to `PINECONE_INDEX_HOST`. */ host?: string; /** Optional Pinecone namespace. */ namespace?: string; }; /** Options forwarded to the local (transformers) embedding adapter. */ local?: { model?: string; }; /** Semantic deduplication on write. Enabled by default. */ deduplication?: DeduplicationConfig; } /** * Browser entry point for turbomem. Same API as {@link TurboMemory} but only * supports PGlite (IndexedDB / in-memory) or a custom {@link StorageAdapter}. */ declare class TurboMemory { private readonly config; private readonly embeddingAdapter; private storageAdapter; private readonly extractor; private readonly merger; private readonly deduplicationConfig; private initialised; private initPromise; constructor(config: TurboMemoryConfig); private static fallbackExtractionKey; private static resolveEmbeddingAdapter; private ensureStorageAdapter; private requireStorageAdapter; init(): Promise; add(messages: Message[], scope: MemoryScope): Promise; addFacts(facts: string[], scope: MemoryScope): Promise; search(query: string, scope: MemoryScope & { limit?: number; }): Promise; getAll(scope: MemoryScope): Promise; delete(id: string): Promise; deleteAll(scope: MemoryScope): Promise; close(): Promise; static newId(): string; private assertInitialised; } /** * Stable, machine-readable error codes thrown by turbomem. */ type TurboMemErrorCode = "NOT_INITIALISED" | "EMBEDDING_FAILED" | "STORAGE_FAILED" | "EXTRACTION_FAILED" | "DIMENSION_MISMATCH" | "INVALID_CONFIG" | "INVALID_INPUT"; /** * Base error class for all turbomem errors. Carries a stable {@link code} so * callers can branch on error type without matching on message strings. */ declare class TurboMemError extends Error { readonly code: TurboMemErrorCode; readonly cause?: unknown; constructor(code: TurboMemErrorCode, message: string, options?: { cause?: unknown; }); } declare class NotInitialisedError extends TurboMemError { constructor(message?: string); } declare class EmbeddingError extends TurboMemError { constructor(message: string, options?: { cause?: unknown; }); } declare class StorageError extends TurboMemError { constructor(message: string, options?: { cause?: unknown; }); } declare class ExtractionError extends TurboMemError { constructor(message: string, options?: { cause?: unknown; }); } declare class DimensionMismatchError extends TurboMemError { constructor(message: string); } declare class ConfigError extends TurboMemError { constructor(message: string); } /** OpenAI embedding models and their output dimensions. */ declare const MODEL_DIMENSIONS$1: Record; type OpenAIEmbeddingModel = keyof typeof MODEL_DIMENSIONS$1 | (string & Record); interface OpenAIEmbeddingOptions { apiKey?: string; baseURL?: string; /** Defaults to `text-embedding-3-small`. */ model?: OpenAIEmbeddingModel; /** Override the dimension count (required for unknown models). */ dimensions?: number; /** Inject a pre-built client (used in tests). */ client?: OpenAI; } declare class OpenAIEmbeddingAdapter implements EmbeddingAdapter { readonly dimensions: number; private readonly client; private readonly model; constructor(options?: OpenAIEmbeddingOptions); embed(text: string): Promise; embedBatch(texts: string[]): Promise; private requestEmbeddings; } /** Voyage embedding models and their default output dimensions. */ declare const MODEL_DIMENSIONS: Record; /** Minimal fetch signature so a stub can be injected in tests. */ type FetchLike = (input: string, init: { method: string; headers: Record; body: string; }) => Promise<{ ok: boolean; status: number; text: () => Promise; json: () => Promise; }>; type VoyageEmbeddingModel = keyof typeof MODEL_DIMENSIONS | (string & Record); interface VoyageEmbeddingOptions { apiKey?: string; /** Full endpoint URL. Defaults to the public Voyage embeddings endpoint. */ baseURL?: string; /** Defaults to `voyage-4`. */ model?: VoyageEmbeddingModel; /** Override the dimension count (sent as `output_dimension`; default 1024). */ dimensions?: number; /** Optional retrieval hint forwarded as `input_type` (`query` | `document`). */ inputType?: "query" | "document"; /** Inject a custom fetch implementation (used in tests). */ fetchImpl?: FetchLike; } declare class VoyageEmbeddingAdapter implements EmbeddingAdapter { readonly dimensions: number; private readonly apiKey; private readonly endpoint; private readonly model; private readonly inputType?; private readonly outputDimension?; private readonly fetchImpl; constructor(options?: VoyageEmbeddingOptions); embed(text: string): Promise; embedBatch(texts: string[]): Promise; private requestEmbeddings; } interface GoogleEmbeddingOptions { apiKey?: string; /** Base URL for the Generative Language API. */ baseURL?: string; /** Defaults to `gemini-embedding-001`. */ model?: string; /** Output dimensionality (128-3072). Defaults to 3072. */ dimensions?: number; /** Optional task type hint (e.g. `RETRIEVAL_DOCUMENT`). */ taskType?: string; /** Inject a custom fetch implementation (used in tests). */ fetchImpl?: FetchLike; } declare class GoogleEmbeddingAdapter implements EmbeddingAdapter { readonly dimensions: number; private readonly apiKey; private readonly baseURL; private readonly model; private readonly taskType?; private readonly fetchImpl; constructor(options?: GoogleEmbeddingOptions); private get outputDimensionality(); embed(text: string): Promise; embedBatch(texts: string[]): Promise; private request; } interface PGliteStorageOptions { /** * Directory to persist the database. Defaults to `.turbomem` in * `process.cwd()` on Node, or `idb://turbomem` in the browser. * * Prefix with `idb://` for IndexedDB persistence in the browser. * Pass `"memory://"` (or set `inMemory`) for an ephemeral database. */ dataDir?: string; /** Use an in-memory database (ignores `dataDir`). Handy for tests. */ inMemory?: boolean; /** * When true, PGlite returns query results before IndexedDB flushes complete. * Defaults to `true` for `idb://` paths; otherwise `false`. */ relaxedDurability?: boolean; } declare class PGliteStorageAdapter implements StorageAdapter { private db; private dimensions; private readonly dataDir; private readonly inMemory; private readonly relaxedDurability; constructor(options?: PGliteStorageOptions); init(dimensions: number): Promise; private requireDb; update(id: string, patch: { content: string; embedding: number[]; metadata?: Record; }): Promise; insert(memory: Omit): Promise; search(embedding: number[], scope: MemoryScope, limit: number): Promise; getAll(scope: MemoryScope): Promise; delete(id: string): Promise; deleteAll(scope: MemoryScope): Promise; close(): Promise; } declare const EXTRACTION_SYSTEM_PROMPT = "You are a memory extraction system for an AI agent. Your job is to extract discrete, reusable facts from a conversation that would be useful to remember in future conversations.\n\nRules:\n- Extract facts that are about the USER, not about the AI's responses\n- Each fact should be a single, standalone statement\n- Facts should be in third person (e.g. \"The user prefers...\" not \"I prefer...\")\n- Only extract facts that are likely to be relevant in future conversations\n- Do not extract facts that are specific to the current task and won't matter later\n- Do not extract opinions the AI expressed\n- If no memorable facts exist, return an empty array\n\nReturn ONLY a JSON array of strings. No explanation, no markdown, no wrapper object.\nExample output: [\"The user prefers concise responses\", \"The user works in TypeScript\"]"; /** * Best-effort parse of an LLM response into an array of fact strings. * Tolerates models that wrap the array in markdown fences or a JSON object. */ declare function parseFacts(raw: string): string[]; interface ExtractorOptions { config: ExtractionConfig; /** Inject a custom completion function (used in tests). */ completion?: (system: string, user: string) => Promise; } /** * Extracts discrete, reusable facts from a conversation using an LLM. * Extraction is treated as non-fatal: on any failure it logs a warning and * returns an empty array rather than throwing. */ declare class Extractor { private readonly config; private readonly completion; constructor(options: ExtractorOptions); extract(messages: Message[]): Promise; private defaultCompletion; private openaiCompletion; private anthropicCompletion; private googleCompletion; } declare const MERGE_SYSTEM_PROMPT = "You are a memory consolidation system for an AI agent. You will receive one or more existing memory facts and one new fact that overlaps with them.\n\nYour job is to return a single consolidated fact that:\n- Is in third person (e.g. \"The user prefers...\" not \"I prefer...\")\n- Combines all unique details from the existing facts and the new fact\n- Prefers the new fact's information when there is a direct conflict\n- Is concise and standalone\n\nReturn ONLY the merged fact as plain text. No explanation, no markdown, no JSON wrapper."; interface MergerOptions { config: ExtractionConfig; /** Inject a custom completion function (used in tests). */ completion?: (system: string, user: string) => Promise; } /** * Consolidates overlapping memory facts using an LLM (Mem0-style multi-way merge). */ declare class Merger { private readonly config; private readonly completion; constructor(options: MergerOptions); mergeMany(existingFacts: string[], newFact: string): Promise; private defaultCompletion; private openaiCompletion; private anthropicCompletion; private googleCompletion; } /** Higher score = more specific / information-dense. */ declare function specificityScore(text: string): number; /** True when `incoming` is more specific than `existing`. */ declare function isMoreSpecific(incoming: string, existing: string): boolean; interface ResolvedDeduplicationConfig { enabled: boolean; threshold: number; strategy: "replace" | "skip" | "merge"; mergeTopK: number; } declare function resolveDeduplicationConfig(config?: DeduplicationConfig): ResolvedDeduplicationConfig; /** * Compute the cosine similarity between two equal-length vectors. * Returns a value in the range [-1, 1]; for normalised embeddings this is * effectively [0, 1]. */ declare function cosineSimilarity(a: number[], b: number[]): number; /** * Split an array into fixed-size chunks. Useful for batching embedding requests * so we respect provider request limits. */ declare function chunkArray(items: T[], size: number): T[][]; /** * Render a list of messages into a single plain-text transcript suitable for * feeding to an extraction LLM. */ declare function formatTranscript(messages: Message[]): string; export { ConfigError, type DeduplicationConfig, type DeduplicationStrategy, DimensionMismatchError, EXTRACTION_SYSTEM_PROMPT, type EmbeddingAdapter, EmbeddingError, type ExtractionConfig, ExtractionError, type ExtractionProvider, Extractor, type ExtractorOptions, type GoogleConfig, GoogleEmbeddingAdapter, type GoogleEmbeddingOptions, MERGE_SYSTEM_PROMPT, type Memory, type MemoryScope, MemoryScopeSchema, type MemorySearchResult, Merger, type MergerOptions, type Message, MessageSchema, MessagesSchema, NotInitialisedError, type OpenAIConfig, OpenAIEmbeddingAdapter, type OpenAIEmbeddingModel, type OpenAIEmbeddingOptions, PGliteStorageAdapter, type PGliteStorageOptions, type ResolvedDeduplicationConfig, type StorageAdapter, StorageError, TurboMemError, type TurboMemErrorCode, TurboMemory, type TurboMemoryConfig, type VoyageConfig, VoyageEmbeddingAdapter, type VoyageEmbeddingModel, type VoyageEmbeddingOptions, chunkArray, cosineSimilarity, formatTranscript, isMoreSpecific, parseFacts, resolveDeduplicationConfig, specificityScore };