import { type MemoryBackend, type MemoryEntry, type PatchReport } from "@sema-agent/core"; import type { MemorySyncStore } from "./plugins/memory-sync-store-pg.js"; /** 一轮同步请求(验型后的干净形状——`parseMemorySyncRequest` 是唯一铸造点)。 */ export interface MemorySyncRequest { /** 对端标识(MemorySyncCursor.peer,per-(scope,peer) 游标分区键)。 */ peer: string; /** 客户端游标的共同基线:id → rev at last completed sync round(空 map = 首轮)。 */ baseRevs: Record; /** push 半场:自基线以来客户端新增/变更的条目全量(scope 已验 = 路径 scope)。 */ entries: MemoryEntry[]; /** 客户端删除的 id(每个都在 baseRevs 里——CAS 基线;验型层保证)。 */ deletes: string[]; /** S2.5 分批腿(契约 settled 2026-07-14,全 additive):pull 半场条目数上限。缺席=不限(旧行为 * 字节不变)。截断规则见 performMemorySync ⑥。 */ pull?: { limit: number; }; } /** 一条冲突上报(applyPatches conflicts 同形 + 入站门/发散两类 reason)。`currentRev` = 中心侧 * 当前 rev(中心已删则缺席)——客户端按 core §3 ladder 解决(败者铸 sibling,绝不静默丢)。 */ export interface MemorySyncConflictReport { id: string; reason: string; baseRev?: string; currentRev?: string; } export interface MemorySyncResponse { /** 中心侧本轮真正落库的 op(backend PatchReport.applied 原样——幂等重放时为空)。 */ applied: PatchReport["applied"]; conflicts: MemorySyncConflictReport[]; /** pull 半场:中心侧自 baseRevs 以来新增/变更的条目全量(客户端按自己的 baseRevs CAS 应用)。 */ serverEntries: MemoryEntry[]; /** pull 半场的删除腿(core plan.deleteRemote;草案偏离①——没它中心删除永不传播 = livelock)。 */ serverDeletes: Array<{ id: string; baseRev: string; }>; /** 本轮落库的新基线(草案偏离②)——客户端应用完 pull 半场后把它持久化为自己的游标。 */ cursor: { peer: string; baseRevs: Record; updatedAtMs: number; }; /** S2.5 分批腿:serverEntries 被 pull.limit 截断时为 true(缺席=未截断)。客户端续轮直到缺席。 */ pullTruncated?: true; } /** 一轮 push 的条目数上限 = core REMOTE_HARVEST_MAX_FILES 同款口径(一个 scope 的文件面上限 500; * 同步一轮打满全集也在此内)。deletes 上限同基数放宽(全集删除也要能一轮表达)。 */ export declare const MEMORY_SYNC_MAX_ENTRIES = 500; export declare const MEMORY_SYNC_MAX_DELETES = 2000; type ParseResult = { ok: true; value: MemorySyncRequest; } | { ok: false; error: string; }; /** Shape-validate + NORMALIZE the request body (picked-not-spread:只挑认识的字段重建,body 上的 * 多余键绝不透传进数据面)。`scope` = 路径上已过 owner 门的 scope——每个条目的 scope 必须逐字 * 等于它(否则一个 owner-gated 路由就成了跨租户写门)。 */ export declare function parseMemorySyncRequest(body: unknown, scope: string): ParseResult; /** * One full sync round for one (scope, peer). `backend` = 中心侧 entry plane(DB 权威),`cursors` = * per-(scope,peer) 游标面(sync_cursors)。纯数据参数进(路由已完成鉴权/owner 门/验型),响应形状出。 */ export declare function performMemorySync(backend: MemoryBackend, cursors: Pick, scope: string, req: MemorySyncRequest, now?: () => number): Promise; export {}; //# sourceMappingURL=memory-sync.d.ts.map