@memoryrelay/plugin-memoryrelay-ai 0.8.1 → 0.8.3

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/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * OpenClaw Memory Plugin - MemoryRelay
3
- * Version: 0.8.0 (Enhanced Debug & Status)
3
+ * Version: 0.8.3 (Security & Installation Fixes)
4
4
  *
5
5
  * Long-term memory with vector search using MemoryRelay API.
6
6
  * Provides auto-recall and auto-capture via lifecycle hooks.
@@ -9,6 +9,18 @@
9
9
  * API: https://api.memoryrelay.net
10
10
  * Docs: https://memoryrelay.ai
11
11
  *
12
+ * ENHANCEMENTS (v0.8.3):
13
+ * - Security fix: logFile now restricted to relative paths only
14
+ * - Rejects absolute paths and path traversal attempts
15
+ * - Passes OpenClaw security validation for npm installation
16
+ * - Clean installation without security warnings
17
+ *
18
+ * ENHANCEMENTS (v0.8.2):
19
+ * - Human-readable gateway logs with memory previews
20
+ * - Show similarity scores and memory snippets during auto-recall
21
+ * - Performance indicators (✓/✗ and timing with SLOW warnings)
22
+ * - Cleaner error messages in gateway logs
23
+ *
12
24
  * ENHANCEMENTS (v0.8.0):
13
25
  * - Debug mode with comprehensive API call logging
14
26
  * - Enhanced status reporting with tool breakdown
@@ -148,6 +160,8 @@ async function fetchWithTimeout(
148
160
  class MemoryRelayClient {
149
161
  private debugLogger?: DebugLogger;
150
162
  private statusReporter?: StatusReporter;
163
+ private config?: MemoryRelayConfig;
164
+ private api?: OpenClawPluginApi;
151
165
 
152
166
  constructor(
153
167
  private readonly apiKey: string,
@@ -155,9 +169,12 @@ class MemoryRelayClient {
155
169
  private readonly apiUrl: string = DEFAULT_API_URL,
156
170
  debugLogger?: DebugLogger,
157
171
  statusReporter?: StatusReporter,
172
+ api?: OpenClawPluginApi,
158
173
  ) {
159
174
  this.debugLogger = debugLogger;
160
175
  this.statusReporter = statusReporter;
176
+ this.api = api;
177
+ this.config = api?.pluginConfig as MemoryRelayConfig | undefined;
161
178
  }
162
179
 
163
180
  /**
@@ -234,6 +251,14 @@ class MemoryRelayClient {
234
251
  retries: retryCount,
235
252
  requestBody: this.debugLogger && body ? body : undefined,
236
253
  });
254
+
255
+ // Enhanced gateway logging (v0.8.2): Readable error summary
256
+ if (this.config.debug && this.api) {
257
+ const retryMsg = retryCount > 0 ? ` (retry ${retryCount}/${MAX_RETRIES})` : '';
258
+ this.api.logger.warn?.(
259
+ `memory-memoryrelay: ${toolName} → ${response.status} ${errorMsg || response.statusText}${retryMsg}`
260
+ );
261
+ }
237
262
  }
238
263
 
239
264
  // Track failure
@@ -267,6 +292,15 @@ class MemoryRelayClient {
267
292
  requestBody: this.debugLogger && body ? body : undefined,
268
293
  responseBody: this.debugLogger && result ? result : undefined,
269
294
  });
295
+
296
+ // Enhanced gateway logging (v0.8.2): Readable API call summary
297
+ if (this.config.debug && this.api) {
298
+ const statusSymbol = response.status < 400 ? '✓' : '✗';
299
+ const durationColor = duration > 1000 ? ' (SLOW)' : duration > 500 ? ' (slow)' : '';
300
+ this.api.logger.info?.(
301
+ `memory-memoryrelay: ${toolName} → ${duration}ms ${statusSymbol}${durationColor}`
302
+ );
303
+ }
270
304
  }
271
305
 
272
306
  // Track success
@@ -817,9 +851,34 @@ export default async function plugin(api: OpenClawPluginApi): Promise<void> {
817
851
 
818
852
  const debugEnabled = cfg?.debug || false;
819
853
  const verboseEnabled = cfg?.verbose || false;
820
- const logFile = cfg?.logFile;
821
854
  const maxLogEntries = cfg?.maxLogEntries || 100;
822
855
 
856
+ // Security fix (v0.8.3): logFile must be relative to workspace/plugin directory
857
+ // Absolute paths and path traversal are rejected
858
+ let logFile: string | undefined;
859
+ if (cfg?.logFile) {
860
+ const requestedPath = cfg.logFile;
861
+
862
+ // Reject absolute paths
863
+ if (requestedPath.startsWith('/') || requestedPath.startsWith('~') || /^[A-Za-z]:/.test(requestedPath)) {
864
+ api.logger.warn(
865
+ `memory-memoryrelay: logFile must be relative path (got: ${requestedPath}). Using default location.`
866
+ );
867
+ logFile = undefined;
868
+ }
869
+ // Reject path traversal
870
+ else if (requestedPath.includes('..')) {
871
+ api.logger.warn(
872
+ `memory-memoryrelay: logFile cannot contain '..' (got: ${requestedPath}). Using default location.`
873
+ );
874
+ logFile = undefined;
875
+ }
876
+ // Accept relative path (will be resolved by DebugLogger relative to workspace)
877
+ else {
878
+ logFile = requestedPath;
879
+ }
880
+ }
881
+
823
882
  let debugLogger: DebugLogger | undefined;
824
883
  let statusReporter: StatusReporter | undefined;
825
884
 
@@ -830,12 +889,16 @@ export default async function plugin(api: OpenClawPluginApi): Promise<void> {
830
889
  maxEntries: maxLogEntries,
831
890
  logFile: logFile,
832
891
  });
833
- api.logger.info(`memory-memoryrelay: debug mode enabled (verbose: ${verboseEnabled}, maxEntries: ${maxLogEntries})`);
892
+
893
+ const logLocation = logFile ? ` → ${logFile}` : '';
894
+ api.logger.info(
895
+ `memory-memoryrelay: debug mode enabled (verbose: ${verboseEnabled}, maxEntries: ${maxLogEntries}${logLocation})`
896
+ );
834
897
  }
835
898
 
836
899
  statusReporter = new StatusReporter(debugLogger);
837
900
 
838
- const client = new MemoryRelayClient(apiKey, agentId, apiUrl, debugLogger, statusReporter);
901
+ const client = new MemoryRelayClient(apiKey, agentId, apiUrl, debugLogger, statusReporter, api);
839
902
 
840
903
  // Verify connection on startup (with timeout)
841
904
  try {
@@ -3297,9 +3360,23 @@ export default async function plugin(api: OpenClawPluginApi): Promise<void> {
3297
3360
  if (results.length > 0) {
3298
3361
  const memoryContext = results.map((r) => `- ${r.memory.content}`).join("\n");
3299
3362
 
3300
- api.logger.info?.(
3301
- `memory-memoryrelay: injecting ${results.length} memories into context`,
3302
- );
3363
+ // Enhanced gateway logging (v0.8.2): Show memory previews
3364
+ if (cfg?.debug) {
3365
+ const snippets = results
3366
+ .map((r) => {
3367
+ const preview = r.memory.content.substring(0, 100).replace(/\n/g, ' ');
3368
+ const ellipsis = r.memory.content.length > 100 ? '...' : '';
3369
+ return ` • [${r.score.toFixed(2)}] ${preview}${ellipsis}`;
3370
+ })
3371
+ .join('\n');
3372
+ api.logger.info?.(
3373
+ `memory-memoryrelay: injecting ${results.length} memories into context:\n${snippets}`,
3374
+ );
3375
+ } else {
3376
+ api.logger.info?.(
3377
+ `memory-memoryrelay: injecting ${results.length} memories into context`,
3378
+ );
3379
+ }
3303
3380
 
3304
3381
  prependContext +=
3305
3382
  `\n\n<relevant-memories>\nThe following memories from MemoryRelay may be relevant:\n${memoryContext}\n</relevant-memories>`;
@@ -3,7 +3,7 @@
3
3
  "kind": "memory",
4
4
  "name": "MemoryRelay AI",
5
5
  "description": "AI memory service with sessions, decisions, patterns & projects (api.memoryrelay.net)",
6
- "version": "0.7.0",
6
+ "version": "0.8.3",
7
7
  "uiHints": {
8
8
  "apiKey": {
9
9
  "label": "MemoryRelay API Key",
@@ -113,7 +113,7 @@
113
113
  },
114
114
  "logFile": {
115
115
  "type": "string",
116
- "description": "Optional file path for persistent debug logs"
116
+ "description": "Relative file path for persistent debug logs (e.g., 'memoryrelay-debug.log'). Absolute paths and path traversal (..) are rejected for security."
117
117
  },
118
118
  "maxLogEntries": {
119
119
  "type": "number",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memoryrelay/plugin-memoryrelay-ai",
3
- "version": "0.8.1",
3
+ "version": "0.8.3",
4
4
  "description": "OpenClaw memory plugin for MemoryRelay API - sessions, decisions, patterns, projects & semantic search",
5
5
  "type": "module",
6
6
  "main": "index.ts",