/** * PR-A Baseline Test 12: Active Memory Plugin * Verifies: active-memory plugin exists, loads, has hook mechanism * Freezes: active-memory plugin contract */ import { describe, it } from "node:test"; import assert from "node:assert"; import { existsSync, readFileSync, readdirSync } from "node:fs"; import { homedir } from "node:os"; import { join } from "node:path"; const OPENCLAW_HOME = "/opt/homebrew/lib/node_modules/openclaw"; const ACTIVE_MEM_DIR = join(OPENCLAW_HOME, "dist", "extensions", "active-memory"); const MEMORY_CORE_DIR = join(OPENCLAW_HOME, "dist", "extensions", "memory-core"); describe("test-12: Active Memory Plugin Baseline", () => { it("12.01 - active-memory plugin directory exists", () => { const exists = existsSync(ACTIVE_MEM_DIR); console.log("[BASELINE] active-memory dir:", ACTIVE_MEM_DIR); console.log("[BASELINE] active-memory dir exists:", exists); if (exists) { const files = readdirSync(ACTIVE_MEM_DIR); console.log("[BASELINE] active-memory files:", files.join(", ")); } assert.ok(exists, "active-memory plugin directory must exist"); }); it("12.02 - active-memory plugin.json has contracts", () => { const pluginPath = join(ACTIVE_MEM_DIR, "openclaw.plugin.json"); if (existsSync(pluginPath)) { const plugin = JSON.parse(readFileSync(pluginPath, "utf8")); console.log("[BASELINE] active-memory plugin id:", plugin.id); console.log("[BASELINE] active-memory onStartup:", plugin.activation?.onStartup); console.log("[BASELINE] active-memory name:", plugin.name); // Check config schema keys if (plugin.configSchema?.properties) { const keys = Object.keys(plugin.configSchema.properties); console.log("[BASELINE] active-memory config keys:", keys.join(", ")); console.log("[BASELINE] active-memory config key count:", keys.length); // Key config fields that must exist assert.ok(keys.includes("enabled"), "must have 'enabled' config"); assert.ok(keys.includes("timeoutMs"), "must have 'timeoutMs' config"); assert.ok(keys.includes("queryMode"), "must have 'queryMode' config"); } } else { console.log("[BASELINE] active-memory plugin.json not found"); } assert.ok(true, "baseline frozen: plugin contract"); }); it("12.03 - memory-core plugin also exists", () => { const exists = existsSync(MEMORY_CORE_DIR); console.log("[BASELINE] memory-core dir exists:", exists); if (exists) { const pluginPath = join(MEMORY_CORE_DIR, "openclaw.plugin.json"); if (existsSync(pluginPath)) { const plugin = JSON.parse(readFileSync(pluginPath, "utf8")); console.log("[BASELINE] memory-core plugin id:", plugin.id); console.log("[BASELINE] memory-core kind:", plugin.kind); console.log("[BASELINE] memory-core contracts:", JSON.stringify(plugin.contracts)); console.log("[BASELINE] memory-core has dreaming:", !!plugin.configSchema?.properties?.dreaming); // Tool contracts are critical const tools = plugin.contracts?.tools || []; console.log("[BASELINE] memory-core tools:", tools.join(", ")); assert.ok(tools.includes("memory_search"), "must register memory_search"); assert.ok(tools.includes("memory_get"), "must register memory_get"); // Dreaming phases const phases = plugin.configSchema?.properties?.dreaming?.properties?.phases?.properties; if (phases) { const phaseNames = Object.keys(phases); console.log("[BASELINE] dreaming phases:", phaseNames.join(", ")); // Freeze: current phase count (light, deep, rem = 3) console.log("[BASELINE] dreaming phase count:", phaseNames.length); } } } assert.ok(exists, "memory-core plugin directory must exist"); }); it("12.04 - active-memory hook mechanism verified", () => { // active-memory uses before_agent_reply hook const pluginPath = join(ACTIVE_MEM_DIR, "openclaw.plugin.json"); if (existsSync(pluginPath)) { const plugin = JSON.parse(readFileSync(pluginPath, "utf8")); // Check if hook is declared in plugin metadata const hasHooks = plugin.hooks !== undefined || plugin.activation?.onStartup === true; console.log("[BASELINE] active-memory has hook declarations:", hasHooks); // Config reveals hook behavior const mode = plugin.configSchema?.properties?.queryMode; if (mode) { console.log("[BASELINE] queryMode options:", mode.enum?.join(", ") || "unknown"); } } // Check that the actual code module loads const indexJs = join(ACTIVE_MEM_DIR, "index.js"); if (existsSync(indexJs)) { const size = readFileSync(indexJs, "utf8").length; console.log("[BASELINE] active-memory index.js size:", size); assert.ok(size > 100, "active-memory code must be substantial"); } assert.ok(true, "baseline frozen: active-memory hook mechanism"); }); it("12.05 - circuit breaker config exists", () => { const pluginPath = join(ACTIVE_MEM_DIR, "openclaw.plugin.json"); if (existsSync(pluginPath)) { const plugin = JSON.parse(readFileSync(pluginPath, "utf8")); const props = plugin.configSchema?.properties || {}; const hasCircuitBreaker = props.circuitBreakerMaxTimeouts !== undefined && props.circuitBreakerCooldownMs !== undefined; console.log("[BASELINE] circuit breaker config:", hasCircuitBreaker); if (hasCircuitBreaker) { console.log("[BASELINE] circuitBreakerMaxTimeouts min:", props.circuitBreakerMaxTimeouts.minimum); console.log("[BASELINE] circuitBreakerCooldownMs min:", props.circuitBreakerCooldownMs.minimum); } } assert.ok(true, "baseline frozen: circuit breaker config"); }); it("12.06 - block mode currently available (blocking path exists)", () => { // Active memory has a blocking mode that runs before agent reply // This test freezes the fact that it exists (not whether it's enabled) const pluginPath = join(ACTIVE_MEM_DIR, "openclaw.plugin.json"); if (existsSync(pluginPath)) { const plugin = JSON.parse(readFileSync(pluginPath, "utf8")); const promptStyle = plugin.configSchema?.properties?.promptStyle; if (promptStyle) { console.log("[BASELINE] promptStyle options:", promptStyle.enum?.join(", ")); assert.ok(promptStyle.enum.length >= 4, "must have multiple prompt styles"); } } assert.ok(true, "baseline frozen: active memory blocking behavior exists"); }); });