import type { MemoryEntry, MemoryStore, MemoryStoreConfig, SearchOptions } from '../../memory/types.js'; import type { ExtractionConfig } from '../../memory/extraction/types.js'; import type { JSONValue } from '../../types/json.js'; /** * Configuration for {@link TestMemoryStore}. * * The store persists to disk by default so the memory records persist across restarts. Set * {@link persist} to `false` for an ephemeral, single session store (useful for e.g. testing). */ export interface TestMemoryStoreConfig extends MemoryStoreConfig { /** * Whether to persist entries to disk so they survive across sessions. * - `true` (default): writes are flushed to {@link path} (or the default location). * - `false`: entries live only in memory and are lost when the process exits. * * @defaultValue true */ persist?: boolean; /** * Full path to the JSON file backing this store. Defaults to * `~/.strands/memory/.json`. Ignored when {@link persist} is `false`. */ path?: string; } /** Result returned by {@link TestMemoryStore.add}. */ export interface TestMemoryAddResult { /** The id of the stored record. */ id: string; } /** * A zero-infrastructure store {@link MemoryStore} that keeps entries in memory and by default * persists them to a local JSON file. Use for prototyping and testing. * * Recall is lexical: results are ranked by how many query tokens overlap an entry's content, with * the most recent entry winning ties. This is keyword matching, not the semantic search a managed * vector store (e.g. {@link BedrockKnowledgeBaseStore}) provides. * * Each {@link add} rewrites the whole file, so this fits modest volumes, not fit for high volume * production workloads. Use a managed store like {@link BedrockKnowledgeBaseStore} for that. * * The on-disk format is shared with the Python SDK's `TestMemoryStore`: records use the same * camelCase keys (`id`, `content`, `metadata`, `createdAt`) and the same timestamp shape, so a * backing file written by either SDK can be read by the other. * * @example * ```typescript * import { TestMemoryStore } from '@strands-agents/sdk/vended-memory-stores/test-memory-store' * * // Persists to ~/.strands/memory/notes.json by default. * const store = new TestMemoryStore({ name: 'notes' }) * * const { id } = await store.add('User prefers dark mode') * const results = await store.search('what theme does the user like?') * ``` */ export declare class TestMemoryStore implements MemoryStore { readonly name: string; readonly description?: string; readonly maxSearchResults?: number; readonly writable: boolean; readonly extraction?: boolean | ExtractionConfig; private readonly _persist; /** Explicit `path` override from config, if any; the default path is resolved lazily in {@link _getPath}. */ private readonly _explicitPath; private _resolvedPath; /** The loaded records once {@link _load} resolves; the working in-memory copy thereafter. */ private _records; /** * Memoizes the first (async) load so concurrent `search`/`add` callers share a single file read * instead of each racing their own — without it, a search interleaved with a first-use add could * overwrite the cache with a pre-write snapshot and drop the just-added record. */ private _loadPromise; /** Serializes writes so concurrent `add`s never interleave the load-modify-flush cycle. */ private _writeChain; constructor(options: TestMemoryStoreConfig); /** * Searches stored entries for those whose content overlaps the query, ranked by token overlap with * the most recent entry winning ties. * * @param query - The search query text * @param options - Optional search configuration * @returns Matching memory entries ordered by relevance. Each entry's `metadata` includes a * `_relevanceScore` key (the token-overlap count). An empty or token-less query returns * no results. */ search(query: string, options?: SearchOptions): Promise; /** * Adds `content` (with optional `metadata`) to the store. Identical content is deduplicated: a * repeat write returns the existing record's id without storing a second copy, so the at-least-once * retries that extraction may perform never accumulate duplicates. * * @param content - The text content to store * @param metadata - Optional metadata to attach to the entry. The key `_relevanceScore` is * reserved: {@link search} populates it on results, so a value stored under it here is * overwritten in search output. * @returns The id of the stored (or already-present) record */ add(content: string, metadata?: Record): Promise; /** * Resolves (and caches) the backing-file path: the explicit `path` from config, else * `~/.strands/memory/.json`. Returns `undefined` for ephemeral stores. The * `node:os`/`node:path` imports are dynamic so the module stays safe to bundle for the browser. */ private _getPath; /** * Loads records from disk on first use; ephemeral stores (and a missing file) start empty. The * first call's promise is memoized in {@link _loadPromise} so concurrent callers await one shared * read rather than each loading independently and racing to assign the cache. */ private _load; /** Reads and parses the backing file (or returns an empty list when ephemeral / missing). */ private _readFromDisk; /** * Persists `records` to disk with an atomic write (write to a `.tmp` file, then rename) so a * crash mid-write can never leave a partially written file. A no-op for ephemeral stores. Callers * serialize invocations via {@link _writeChain}. Throws with the target path (and the OS error as * `cause`) when the path is unreachable or not writable. */ private _flush; } //# sourceMappingURL=store.d.ts.map