import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; import { MengramClient } from "./client.ts"; import { parseConfig } from "./config.ts"; import { initLogger } from "./logger.ts"; import { buildRecallHandler } from "./hooks/recall.ts"; import { buildCaptureHandler } from "./hooks/capture.ts"; import { registerSearchTool } from "./tools/search.ts"; import { registerStoreTool } from "./tools/store.ts"; import { registerForgetTool } from "./tools/forget.ts"; import { registerProfileTool } from "./tools/profile.ts"; import { registerProceduresTool } from "./tools/procedures.ts"; import { registerFeedbackTool } from "./tools/feedback.ts"; import { registerEpisodesTool } from "./tools/episodes.ts"; import { registerTimelineTool } from "./tools/timeline.ts"; import { registerTriggersTool } from "./tools/triggers.ts"; import { registerInsightsTool } from "./tools/insights.ts"; import { registerAgentsTool } from "./tools/agents.ts"; import { registerGraphTool } from "./tools/graph.ts"; import { registerSlashCommands } from "./commands/slash.ts"; import { registerCli } from "./commands/cli.ts"; export default { id: "openclaw-mengram", name: "Mengram", description: "Human-like long-term memory — semantic facts, episodic events, " + "and self-improving procedural workflows with Graph RAG", kind: "memory" as const, register(api: OpenClawPluginApi) { const cfg = parseConfig(api.pluginConfig); const log = initLogger(api.logger, cfg); if (!cfg.apiKey) { log.warn( "no API key configured — set apiKey in plugin config or MENGRAM_API_KEY env var. " + "Get a free key at https://mengram.io", ); // Register stub slash commands so user gets helpful error messages api.registerCommand({ name: "remember", description: "Save to memory (not configured)", handler: () => ({ text: "Mengram not configured. Set your API key in plugin config or MENGRAM_API_KEY env var.", }), }); api.registerCommand({ name: "recall", description: "Search memory (not configured)", handler: () => ({ text: "Mengram not configured. Set your API key in plugin config or MENGRAM_API_KEY env var.", }), }); api.registerCommand({ name: "forget", description: "Delete from memory (not configured)", handler: () => ({ text: "Mengram not configured. Set your API key in plugin config or MENGRAM_API_KEY env var.", }), }); return; } const client = new MengramClient(cfg.apiKey, cfg.baseUrl, cfg.requestTimeout); log.info("connected"); // Register 12 tools registerSearchTool(api, client, cfg, log); registerStoreTool(api, client, cfg, log); registerForgetTool(api, client, cfg, log); registerProfileTool(api, client, cfg, log); registerProceduresTool(api, client, cfg, log); registerFeedbackTool(api, client, cfg, log); registerEpisodesTool(api, client, cfg, log); registerTimelineTool(api, client, cfg, log); registerTriggersTool(api, client, cfg, log); registerInsightsTool(api, client, cfg, log); registerAgentsTool(api, client, cfg, log); registerGraphTool(api, client, cfg, log); // Auto-recall: inject memories before each agent turn // Use before_prompt_build (OpenClaw >=2026.3.22) with before_agent_start fallback if (cfg.autoRecall) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const apiAny = api as any; const hasNewHook = typeof apiAny.hasHook === "function" && apiAny.hasHook("before_prompt_build"); const recallHandler = buildRecallHandler(client, cfg, log, !hasNewHook) as ( ...args: unknown[] ) => unknown; if (hasNewHook) { api.on("before_prompt_build", recallHandler); log.info("auto-recall enabled (before_prompt_build)"); } else { api.on("before_agent_start", recallHandler); log.info("auto-recall enabled (before_agent_start, legacy)"); } } // Auto-capture: store memories after each agent turn if (cfg.autoCapture) { api.on( "agent_end", buildCaptureHandler(client, cfg, log) as ( ...args: unknown[] ) => unknown, ); log.info("auto-capture enabled"); } // Slash commands: /remember, /recall, /forget registerSlashCommands(api, client, cfg, log); // CLI: openclaw mengram search/stats/profile/procedures registerCli(api, client, cfg, log); // Service lifecycle api.registerService({ id: "openclaw-mengram", start: () => log.info("service started"), stop: () => log.info("service stopped"), }); }, };