// Memory Core plugin module implements memory tool manager mock behavior. import type { MemorySearchRuntimeDebug } from "openclaw/plugin-sdk/memory-core-host-runtime-files"; import { vi } from "vitest"; type SearchImpl = (opts?: { maxResults?: number; minScore?: number; sessionKey?: string; qmdSearchModeOverride?: "query" | "search" | "vsearch"; onDebug?: (debug: MemorySearchRuntimeDebug) => void; signal?: AbortSignal; }) => Promise; export type MemoryReadParams = { relPath: string; from?: number; lines?: number }; type MemoryReadResult = { text: string; path: string; truncated?: boolean; from?: number; lines?: number; nextFrom?: number; }; type MemoryBackend = "builtin" | "qmd"; let backend: MemoryBackend = "builtin"; let workspaceDir = "/workspace"; let customStatus: Record | undefined; let searchImpl: SearchImpl = async () => []; let getManagerImpl: | ((params: { cfg?: unknown; agentId?: string; purpose?: string }) => Promise<{ manager?: unknown; error?: string; }>) | undefined; let readFileImpl: (params: MemoryReadParams) => Promise = async (params) => ({ text: "", path: params.relPath, from: params.from ?? 1, lines: params.lines ?? 120, }); const stubManager = { search: vi.fn(async (_query: string, opts?: Parameters[0]) => await searchImpl(opts)), readFile: vi.fn(async (params: MemoryReadParams) => await readFileImpl(params)), status: () => ({ backend, files: 1, chunks: 1, dirty: false, workspaceDir, dbPath: "/workspace/.memory/index.sqlite", provider: "builtin", model: "builtin", requestedProvider: "builtin", sources: ["memory" as const], sourceCounts: [{ source: "memory" as const, files: 1, chunks: 1 }], custom: customStatus, }), sync: vi.fn(), probeVectorAvailability: vi.fn(async () => true), close: vi.fn(), }; const getMemorySearchManagerMock = vi.fn( async (params: { cfg?: unknown; agentId?: string; purpose?: string }) => getManagerImpl ? await getManagerImpl(params) : { manager: stubManager }, ); const readAgentMemoryFileMock = vi.fn( async (params: MemoryReadParams) => await readFileImpl(params), ); vi.mock("./tools.runtime.js", () => ({ resolveMemoryBackendConfig: ({ cfg, }: { cfg?: { memory?: { backend?: string; qmd?: unknown } }; }) => ({ backend, qmd: cfg?.memory?.qmd, }), getMemorySearchManager: getMemorySearchManagerMock, readAgentMemoryFile: readAgentMemoryFileMock, })); export function setMemoryBackend(next: MemoryBackend): void { backend = next; } export function setMemoryWorkspaceDir(next: string): void { workspaceDir = next; } export function setMemoryCustomStatus(next: Record | undefined): void { customStatus = next; } export function setMemorySearchImpl(next: SearchImpl): void { searchImpl = next; } export function setMemorySearchManagerImpl( next: (params: { cfg?: unknown; agentId?: string; purpose?: string }) => Promise<{ manager?: unknown; error?: string; }>, ): void { getManagerImpl = next; } export function setMemoryReadFileImpl( next: (params: MemoryReadParams) => Promise, ): void { readFileImpl = next; } export function resetMemoryToolMockState(overrides?: { backend?: MemoryBackend; searchImpl?: SearchImpl; readFileImpl?: (params: MemoryReadParams) => Promise; }): void { backend = overrides?.backend ?? "builtin"; workspaceDir = "/workspace"; customStatus = undefined; getManagerImpl = undefined; searchImpl = overrides?.searchImpl ?? (async () => []); readFileImpl = overrides?.readFileImpl ?? (async (params: MemoryReadParams) => ({ text: "", path: params.relPath, from: params.from ?? 1, lines: params.lines ?? 120, })); vi.clearAllMocks(); } export function getMemorySearchManagerMockCalls(): number { return getMemorySearchManagerMock.mock.calls.length; } export function getMemorySyncMockCalls(): number { return stubManager.sync.mock.calls.length; } export function getMemoryCloseMockCalls(): number { return stubManager.close.mock.calls.length; } export function getMemorySearchManagerMockConfigs(): unknown[] { return getMemorySearchManagerMock.mock.calls.map(([params]) => params.cfg); } export function getMemorySearchManagerMockParams(): Array<{ cfg?: unknown; agentId?: string; purpose?: string; }> { return getMemorySearchManagerMock.mock.calls.map(([params]) => params); } export function getReadAgentMemoryFileMockCalls(): number { return readAgentMemoryFileMock.mock.calls.length; }