@mem9/mem9 0.3.5-rc.5 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/hooks.ts CHANGED
@@ -130,11 +130,14 @@ function formatMemoriesBlock(memories: Memory[]): string {
130
130
  let idx = 1;
131
131
 
132
132
  const formatMem = (m: Memory): string => {
133
- const tags = m.tags?.length ? ` [${m.tags.join(", ")}]` : "";
133
+ const tagStr = m.tags?.length ? `[${m.tags.join(", ")}]` : "";
134
+ const age = m.relative_age ? `(${m.relative_age})` : "";
135
+ const middle = [tagStr, age].filter(Boolean).join(" ");
136
+ const sep = middle ? " " + middle + " " : " ";
134
137
  const content = m.content.length > MAX_CONTENT_LEN
135
138
  ? m.content.slice(0, MAX_CONTENT_LEN) + "..."
136
139
  : m.content;
137
- return `${idx++}.${tags} ${escapeForPrompt(content)}`;
140
+ return `${idx++}.${sep}${escapeForPrompt(content)}`;
138
141
  };
139
142
 
140
143
  if (pinned.length > 0) {
package/index.ts CHANGED
@@ -3,6 +3,7 @@ import { ServerBackend } from "./server-backend.js";
3
3
  import { registerHooks } from "./hooks.js";
4
4
  import type {
5
5
  PluginConfig,
6
+ Memory,
6
7
  CreateMemoryInput,
7
8
  UpdateMemoryInput,
8
9
  SearchInput,
@@ -26,6 +27,13 @@ function jsonResult(data: unknown) {
26
27
  }
27
28
  }
28
29
 
30
+ interface MemoryCapability {
31
+ search: (query: string, opts?: { limit?: number }) => Promise<{ data: Memory[]; total: number }>;
32
+ store: (content: string, opts?: { tags?: string[]; source?: string }) => Promise<unknown>;
33
+ get: (id: string) => Promise<Memory | null>;
34
+ remove: (id: string) => Promise<boolean>;
35
+ }
36
+
29
37
  interface OpenClawPluginApi {
30
38
  pluginConfig?: unknown;
31
39
  logger: {
@@ -36,6 +44,7 @@ interface OpenClawPluginApi {
36
44
  factory: ToolFactory | (() => AnyAgentTool[]),
37
45
  opts: { names: string[] }
38
46
  ) => void;
47
+ registerCapability?: (slot: string, capability: MemoryCapability) => void;
39
48
  on: (hookName: string, handler: (...args: unknown[]) => unknown, opts?: { priority?: number }) => void;
40
49
  }
41
50
 
@@ -123,6 +132,10 @@ function buildTools(backend: MemoryBackend): AnyAgentTool[] {
123
132
  description: "Max results (default 20, max 200)",
124
133
  },
125
134
  offset: { type: "number", description: "Pagination offset" },
135
+ memory_type: {
136
+ type: "string",
137
+ description: "Comma-separated memory types to filter by (e.g. insight,pinned)",
138
+ },
126
139
  },
127
140
  required: [],
128
141
  },
@@ -238,7 +251,7 @@ const mnemoPlugin = {
238
251
  description:
239
252
  "AI agent memory — server mode (mnemo-server) with hybrid vector + keyword search.",
240
253
 
241
- async register(api: OpenClawPluginApi) {
254
+ register(api: OpenClawPluginApi) {
242
255
  const cfg = (api.pluginConfig ?? {}) as PluginConfig;
243
256
  const effectiveApiUrl = cfg.apiUrl ?? DEFAULT_API_URL;
244
257
  if (!cfg.apiUrl) {
@@ -284,13 +297,32 @@ const mnemoPlugin = {
284
297
 
285
298
  api.registerTool(factory, { names: toolNames });
286
299
 
287
- // Register hooks with a lazy backend for lifecycle memory management.
288
- // Uses the default workspace/agent context for hook-triggered operations.
300
+ // Shared lazy backend for hooks and capability registration.
289
301
  const hookBackend = new LazyServerBackend(
290
302
  effectiveApiUrl,
291
303
  () => resolveAPIKey(hookAgentId),
292
304
  hookAgentId,
293
305
  );
306
+
307
+ // Register memory capability so OpenClaw 2026.4.2+ binds this plugin to
308
+ // the memory slot. Without this, the plugin is treated as a legacy
309
+ // hook-only plugin and automatic context injection won't work.
310
+ // Guard with typeof check for backward compatibility with older hosts.
311
+ if (typeof api.registerCapability === "function") {
312
+ api.registerCapability("memory", {
313
+ search: async (query, opts) => {
314
+ const result = await hookBackend.search({ q: query, limit: opts?.limit });
315
+ return { data: result.data, total: result.total };
316
+ },
317
+ store: async (content, opts) => {
318
+ return hookBackend.store({ content, tags: opts?.tags, source: opts?.source });
319
+ },
320
+ get: (id) => hookBackend.get(id),
321
+ remove: (id) => hookBackend.remove(id),
322
+ });
323
+ }
324
+
325
+ // Register hooks with lazy backend for lifecycle memory management.
294
326
  registerHooks(api, hookBackend, api.logger, {
295
327
  maxIngestBytes: cfg.maxIngestBytes,
296
328
  fallbackAgentId: hookAgentId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mem9/mem9",
3
- "version": "0.3.5-rc.5",
3
+ "version": "0.3.6",
4
4
  "description": "OpenClaw shared memory plugin — cloud-persistent memory with hybrid vector + keyword search via mnemo-server",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
package/server-backend.ts CHANGED
@@ -67,6 +67,7 @@ export class ServerBackend implements MemoryBackend {
67
67
  if (input.source) params.set("source", input.source);
68
68
  if (input.limit != null) params.set("limit", String(input.limit));
69
69
  if (input.offset != null) params.set("offset", String(input.offset));
70
+ if (input.memory_type) params.set("memory_type", input.memory_type);
70
71
 
71
72
  const qs = params.toString();
72
73
  const raw = await this.request<{
package/types.ts CHANGED
@@ -31,6 +31,8 @@ export interface Memory {
31
31
  state?: string;
32
32
  agent_id?: string;
33
33
  session_id?: string;
34
+
35
+ relative_age?: string;
34
36
  }
35
37
 
36
38
  export interface SearchResult {
@@ -60,6 +62,7 @@ export interface SearchInput {
60
62
  source?: string;
61
63
  limit?: number;
62
64
  offset?: number;
65
+ memory_type?: string;
63
66
  }
64
67
 
65
68
  export interface IngestMessage {