import { Block, Episode, Fact, MemoryHit, MemoryRecord, MemorySearchOptions, Rule } from "../types/memory.js"; import { Message } from "../types/message.js"; import { RunTurnVerdict } from "../types/run.js"; import { SessionScope } from "../types/session-scope.js"; //#region src/contracts/memory-store.d.ts /** * Persistent storage interface for the six memory tiers. Implementations * live in the storage adapter packages (`@graphorin/store-sqlite` is the * default). * * Sub-namespaces map 1:1 to the six tiers so each implementation can * pick its own physical layout (one big table, six tables, mixed) while * preserving append-only semantics - soft-delete only. * * **Baseline vs full adapter.** This interface is the MINIMUM a * third-party adapter must implement; `@graphorin/memory` accepts it and * degrades gracefully (vector search, decay, consolidation, insights, * graph expansion, conflict audit switch off where the surface is * absent). Full feature parity with `@graphorin/store-sqlite` (asOf * reads, vector KNN, decay signals, insights, entity graph, conflicts, * consolidator state/DLQ) is described by `MemoryStoreAdapter` and the * `*MemoryStoreExt` interfaces exported from the root of * `@graphorin/memory`. Every Ext addition over the six tier namespaces * is optional BY CONTRACT - a type test in `@graphorin/memory` pins * `MemoryStore extends MemoryStoreAdapter`, so a core-only adapter can * never stop compiling. * * @stable */ interface MemoryStore { readonly working: WorkingMemoryStore; readonly session: SessionMemoryStore; readonly episodic: EpisodicMemoryStore; readonly semantic: SemanticMemoryStore; readonly procedural: ProceduralMemoryStore; readonly shared: SharedMemoryStore; /** Initialize / migrate the underlying storage. Idempotent. */ init(): Promise; /** Cleanly close any underlying handles. Idempotent. */ close(): Promise; } /** * Maintenance extension over {@link MemoryStore}, mirroring * the `SessionStoreExt` precedent: capabilities the sqlite adapter * guarantees but a custom `MemoryStore` is not obliged to implement. * The base contract is unchanged - existing implementations keep * compiling. * * @stable */ interface MemoryStoreExt extends MemoryStore { /** * Delete `memory_history` rows older than the given AGE in * milliseconds. The argument is an AGE (the implementation computes * `cutoff = now - olderThanMs`), never an epoch cutoff - passing an * epoch value would compute a nonsense cutoff far in the past and * silently prune nothing. Returns the number of rows removed. * History grows by design (every supersede / quarantine transition * appends) and `purge()` already scrubs sensitive text; this is the * storage-cost hygiene lever - nothing prunes automatically. */ pruneHistory(olderThanMs: number): Promise; } /** @stable */ interface WorkingMemoryStore { list(scope: SessionScope): Promise>; get(scope: SessionScope, label: string): Promise; upsert(scope: SessionScope, block: Block): Promise; delete(scope: SessionScope, label: string, reason?: string): Promise; /** * Hard-delete a block row - no tombstone left behind. * `delete` stays the soft tombstone; `purge` is the GDPR path for * USER-scoped blocks (e.g. the `profile` projection), which the * session-delete cascade never reaches (`scope_session_id IS NULL`). * Optional-additive: adapters that do not implement it make * `WorkingMemory.purge` throw instead of silently soft-deleting. */ purge?(scope: SessionScope, label: string): Promise; } /** * Reference returned by `SessionMemoryStore.push(...)`. Carries the * persisted message id and a sequence number for ordering. * * @stable */ interface MessageRef { readonly messageId: string; readonly sequence: number; readonly persistedAt: string; } /** * A stored message paired with its persisted identity. The {@link Message} * type itself carries no id / timestamp; these come from the store row, so an * exporter can preserve message identity + chronology across a round-trip. * * @stable */ interface SessionMessageWithMetadata { readonly message: Message; readonly messageId: string; readonly sequence: number; readonly createdAt: string; } /** * Optional per-message write metadata. `verdict` is the * turn's security verdict from the run loop's commit gates * (`RunState.verdicts`); persisted so the memory ingest gate can * exclude guardrail-blocked turns from extraction deterministically. * Additive third argument (arity precedent: `forget(id, reason?, * scope?)`); widen-only semantics like `ToolReturn.taint`. * * @stable */ interface SessionMessagePushOptions { readonly verdict?: RunTurnVerdict; } /** @stable */ interface SessionMemoryStore { push(scope: SessionScope, message: Message, options?: SessionMessagePushOptions): Promise; list(scope: SessionScope, opts?: SessionListOptions): Promise>; /** * List messages with their persisted identity. Optional: stores that * don't implement it fall back to `list` + fabricated ids on the export path. */ listWithMetadata?(scope: SessionScope, opts?: SessionListOptions): Promise>; /** * Full-text search over the scoped session messages. * * Query precedence: the POSITIONAL `query` parameter is * authoritative; when the caller also sets `opts.query` (the field * exists because {@link MemorySearchOptions} is shared with the * option-object search surfaces), implementations MUST ignore it. * The duplication is a known wart: narrowing `opts` to * `Omit` is a candidate for the next * major, not a change this line can make compatibly. */ search(scope: SessionScope, query: string, opts?: MemorySearchOptions): Promise>; } /** @stable */ interface SessionListOptions { readonly lastN?: number; readonly sinceMessageId?: string; readonly agentId?: string; readonly role?: 'system' | 'user' | 'assistant' | 'tool'; } /** @stable */ interface EpisodicMemoryStore { put(episode: Episode): Promise; search(scope: SessionScope, opts: MemorySearchOptions): Promise>>; get(id: string): Promise; } /** @stable */ interface SemanticMemoryStore { remember(fact: Fact): Promise; search(scope: SessionScope, opts: MemorySearchOptions): Promise>>; supersede(oldId: string, newFact: Fact, reason?: string): Promise; /** * Soft-delete a fact. When `scope` is supplied, adapters that * support tenant isolation MUST treat a fact outside the scope as a * deterministic no-op (0 rows changed) - defense in depth so a * leaked / cross-user id reaching a mutator cannot touch another * user's memory. Omitting `scope` preserves the historical unscoped * behaviour (trusted internal callers: consolidator, erasure * cascades). The parameter is additive - existing adapter * implementations with the narrower arity remain structurally * compatible. */ forget(id: string, reason?: string, scope?: SessionScope): Promise; } /** @stable */ interface ProceduralMemoryStore { add(rule: Rule): Promise; list(scope: SessionScope): Promise>; remove(id: string, reason?: string): Promise; } /** @stable */ interface SharedMemoryStore { attach(recordId: string, agentId: string): Promise; detach(recordId: string, agentId: string): Promise; listFor(agentId: string): Promise>; } //#endregion export { EpisodicMemoryStore, MemoryStore, MemoryStoreExt, MessageRef, ProceduralMemoryStore, SemanticMemoryStore, SessionListOptions, SessionMemoryStore, SessionMessagePushOptions, SessionMessageWithMetadata, SharedMemoryStore, WorkingMemoryStore }; //# sourceMappingURL=memory-store.d.ts.map