import { describe, expect, it, vi } from "vitest"; type Capability = { promptBuilder?: (params: { availableTools: Set; }) => string[] | undefined; }; type RegisterFn = (capability: Capability) => void; interface FakeApi { registerMemoryCapability: RegisterFn; on: ReturnType; pluginConfig: Record; logger: { warn: ReturnType }; } function makeApi(overrides: Partial = {}): FakeApi { return { registerMemoryCapability: vi.fn(), on: vi.fn(), pluginConfig: { base_url: "http://localhost:3111" }, logger: { warn: vi.fn() }, ...overrides, }; } describe("openclaw plugin — memory capability registration (closes #286 follow-up)", () => { it("calls api.registerMemoryCapability with a promptBuilder when the host supports it", async () => { const mod = await import("../integrations/openclaw/plugin.mjs"); const plugin = (mod as unknown as { default: { register(api: FakeApi): void } }).default; const api = makeApi(); plugin.register(api); expect(api.registerMemoryCapability).toHaveBeenCalledTimes(1); const capability = (api.registerMemoryCapability as ReturnType).mock.calls[0][0] as Capability; expect(typeof capability.promptBuilder).toBe("function"); const lines = capability.promptBuilder?.({ availableTools: new Set() }); expect(Array.isArray(lines)).toBe(true); expect((lines as string[]).join(" ")).toMatch(/agentmemory/i); }); it("still registers hooks and tolerates older OpenClaw builds without registerMemoryCapability", async () => { const mod = await import("../integrations/openclaw/plugin.mjs"); const plugin = (mod as unknown as { default: { register(api: FakeApi): void } }).default; const api = makeApi({ registerMemoryCapability: undefined as unknown as RegisterFn }); expect(() => plugin.register(api)).not.toThrow(); expect(api.on).toHaveBeenCalled(); const events = (api.on as ReturnType).mock.calls.map((c) => c[0]); expect(events).toContain("before_agent_start"); expect(events).toContain("agent_end"); }); it("promptBuilder returns lines that mention the configured base_url", async () => { const mod = await import("../integrations/openclaw/plugin.mjs"); const plugin = (mod as unknown as { default: { register(api: FakeApi): void } }).default; const api = makeApi({ pluginConfig: { base_url: "http://memory.internal:9999" } }); plugin.register(api); const capability = (api.registerMemoryCapability as ReturnType).mock.calls[0][0] as Capability; const lines = capability.promptBuilder?.({ availableTools: new Set() }) ?? []; expect(lines.join("\n")).toMatch(/memory\.internal:9999/); }); });