import type { MemoryHistoryAppendRow } from "./memory-sync-store-pg.js"; import type { PgEmbedder, PgQueryFn } from "./pg-query.js"; import type { MemoryBackend, MemoryEntry, MemoryEntryHeader, NotePatch, PatchReport, ScoredMemoryEntry } from "@sema-agent/core"; import { type IndexSpec } from "./ensure-index.js"; /** Table names (single source). Deliberately DISJOINT from the legacy `agent_memory*` tables — * the retired MemoryStore plane and this entry plane must never cross-write. */ export declare const PG_MEMORY_ENGINE_TABLES: { readonly entry: "agent_memory_engine_entry"; readonly cursor: "agent_memory_engine_cursor"; }; /** Options for {@link ensurePgMemoryEngineSchema} — same `memoryVector` contract as PgAgentSchemaOptions. */ export interface PgMemoryEngineSchemaOptions { /** Omitted → `jsonb` embedding column (portable). `{ dimensions, pgvector: true }` → `CREATE EXTENSION * vector` + a `vector(d)` column (native `<=>`). Pick once; keep the backend options consistent. */ memoryVector?: { dimensions: number; pgvector?: boolean; }; } /** S-287:记忆引擎 PG 面的索引**声明**(MySQL 孪生是 `memory-engine-tidb.ts` 的内联 `KEY`/`UNIQUE KEY`, * 由 `tidb-pool.ts` 的中央 `ensureSchema` 用同一份声明补存量库)。 */ export declare const MEMORY_ENGINE_INDEXES: readonly IndexSpec[]; /** Idempotent DDL for the entry plane. Call once at startup (or run through your migration tool). */ export declare function ensurePgMemoryEngineSchema(query: PgQueryFn, opts?: PgMemoryEngineSchemaOptions): Promise; /** Options for {@link PgMemoryEngineBackend}. */ export interface PgMemoryEngineBackendOptions { /** Entries are embedded on add/update and `search` ranks by cosine distance. Absent → lexical floor. */ embedder?: PgEmbedder; /** `true` → rank in SQL via pgvector `<=>` (schema must carry `memoryVector: { pgvector: true }`). * Same migration note as PgMemoryStoreOptions: the SQL path EXCLUDES rows without an embedding — * backfill before enabling. Requires `embedder`. */ pgvectorSql?: boolean; /** Clock injection (file-backend precedent) — drives `mtime_ms`. Default `Date.now`. */ now?: () => number; /** 142-S5.1 history write point (改动 vs origin): OPTIONAL audit sink — every APPLIED * patch appends one `agent_memory_engine_history` row (add=chain head/update=prevRev link/ * delete=tombstone) AFTER its entry write commits. Absent → byte-equal legacy behavior (additive). * ⚠️ 同事务诚实记档:the 142-S4 design draft says "同事务追加", but this backend's ONLY DB seam is * a bare `PgQueryFn` — with a pooled query fn, BEGIN/COMMIT statements may land on DIFFERENT * connections, so a true transaction would require refactoring the constructor to a client-checkout * seam (breaks the origin-core@3071dd3 minimal-diff move-in discipline). * Chosen trade-off: entry write commits first, history append is BEST-EFFORT * (failure = swallow + console.warn) — history is the AUDIT face, not the correctness face: a lost * history row loses an audit line, never data (the entries table stays the single truth). */ history?: { appendHistory(rows: readonly MemoryHistoryAppendRow[]): Promise; }; } export declare class PgMemoryEngineBackend implements MemoryBackend { private readonly query; private readonly embedder?; private readonly pgvectorSql; private readonly clock; private readonly history?; /** Cumulative lost-row count — audit-line breakage must itself be auditable. */ private historyRowsLost; /** [ref] rung indicator — same semantics as PgMemoryStore.vectorMode. */ get vectorMode(): "native" | "portable" | "lexical"; constructor(query: PgQueryFn, opts?: PgMemoryEngineBackendOptions); /** The embed/search haystack — BYTE-EQUAL to FileBackend's lexical haystack (file-backend search). */ private haystackOf; /** Dimension-guarded embedding parameter (mirrors PgMemoryStore.embeddingParam — wrong-length ⇒ null, * the row falls open to the lexical stand-in instead of poisoning reads). */ private embeddingParam; private headerFromRow; private entryFromRow; listHeaders(scopes: readonly string[]): Promise; getByIds(ids: readonly string[]): Promise; search(query: string, scopes: readonly string[], opts?: { limit?: number; exposureBands?: boolean; }): Promise; applyPatches(patches: readonly NotePatch[]): Promise; private applyOne; /** When the conditional write returns zero rows (a write landed inside the * SELECT→write window), the report's `currentRev` must be the rev NOW — re-reporting the pre-race * SELECT value could claim `baseRev === currentRev` alongside a "rev mismatch" reason. */ private freshRev; getConsolidationCursor(scope: string): Promise; setConsolidationCursor(scope: string, cursor: string): Promise; } //# sourceMappingURL=memory-engine-pg.d.ts.map