@memoryrelay/plugin-memoryrelay-ai 0.11.2 → 0.11.4

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.
Files changed (2) hide show
  1. package/index.ts +267 -11
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * OpenClaw Memory Plugin - MemoryRelay
3
- * Version: 0.11.2 (Full Single-File)
3
+ * Version: 0.11.4 (Full Single-File)
4
4
  *
5
5
  * Long-term memory with vector search using MemoryRelay API.
6
6
  * Provides auto-recall and auto-capture via lifecycle hooks.
@@ -101,23 +101,279 @@ class DebugLogger {
101
101
  // StatusReporter (Inlined from src/status-reporter.ts)
102
102
  // ============================================================================
103
103
 
104
+ interface ToolStatus {
105
+ enabled: number;
106
+ available: number;
107
+ failed: number;
108
+ tools: {
109
+ name: string;
110
+ status: "working" | "error" | "unknown";
111
+ error?: string;
112
+ lastSuccess?: string;
113
+ lastError?: string;
114
+ }[];
115
+ }
116
+
117
+ interface ConnectionStatus {
118
+ status: "connected" | "disconnected" | "degraded";
119
+ endpoint: string;
120
+ lastCheck: string;
121
+ responseTime: number;
122
+ }
123
+
124
+ interface MemoryStats {
125
+ total_memories: number;
126
+ memories_today?: number;
127
+ last_stored?: string;
128
+ search_count_24h?: number;
129
+ }
130
+
131
+ interface PluginConfig {
132
+ agentId: string;
133
+ autoRecall: boolean;
134
+ autoCapture: boolean;
135
+ recallLimit: number;
136
+ recallThreshold: number;
137
+ excludeChannels: string[];
138
+ defaultProject?: string;
139
+ }
140
+
141
+ interface StatusReport {
142
+ connection: ConnectionStatus;
143
+ config: PluginConfig;
144
+ stats: MemoryStats;
145
+ tools: Record<string, ToolStatus>;
146
+ recentCalls: LogEntry[];
147
+ issues: { tool: string; error: string; since: string }[];
148
+ }
149
+
104
150
  class StatusReporter {
105
- constructor(private debugLogger?: DebugLogger) {}
151
+ private debugLogger?: DebugLogger;
152
+ private toolFailures: Map<string, { error: string; since: string }> = new Map();
153
+
154
+ constructor(debugLogger?: DebugLogger) {
155
+ this.debugLogger = debugLogger;
156
+ }
157
+
158
+ /**
159
+ * Record tool failure
160
+ */
161
+ recordFailure(toolName: string, error: string): void {
162
+ if (!this.toolFailures.has(toolName)) {
163
+ this.toolFailures.set(toolName, {
164
+ error,
165
+ since: new Date().toISOString(),
166
+ });
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Record tool success (clears failure)
172
+ */
173
+ recordSuccess(toolName: string): void {
174
+ this.toolFailures.delete(toolName);
175
+ }
176
+
177
+ /**
178
+ * Get known issues
179
+ */
180
+ getIssues(): { tool: string; error: string; since: string }[] {
181
+ return Array.from(this.toolFailures.entries()).map(([tool, data]) => ({
182
+ tool,
183
+ error: data.error,
184
+ since: data.since,
185
+ }));
186
+ }
187
+
188
+ /**
189
+ * Build status report
190
+ */
191
+ buildReport(
192
+ connection: ConnectionStatus,
193
+ config: PluginConfig,
194
+ stats: MemoryStats,
195
+ toolGroups: Record<string, string[]>
196
+ ): StatusReport {
197
+ const recentCalls = this.debugLogger
198
+ ? this.debugLogger.getRecentLogs(10)
199
+ : [];
200
+
201
+ const tools: Record<string, ToolStatus> = {};
202
+
203
+ for (const [group, toolNames] of Object.entries(toolGroups)) {
204
+ const toolStatuses = toolNames.map(name => {
205
+ const logs = this.debugLogger?.getToolLogs(name, 1) || [];
206
+ const lastLog = logs[0];
207
+ const failure = this.toolFailures.get(name);
208
+
209
+ let status: "working" | "error" | "unknown" = "unknown";
210
+ let error: string | undefined;
211
+ let lastSuccess: string | undefined;
212
+ let lastError: string | undefined;
213
+
214
+ if (lastLog) {
215
+ status = lastLog.status === "success" ? "working" : "error";
216
+ if (lastLog.status === "success") {
217
+ lastSuccess = lastLog.timestamp;
218
+ } else {
219
+ lastError = lastLog.timestamp;
220
+ error = lastLog.error;
221
+ }
222
+ } else if (failure) {
223
+ status = "error";
224
+ error = failure.error;
225
+ lastError = failure.since;
226
+ }
227
+
228
+ return {
229
+ name,
230
+ status,
231
+ error,
232
+ lastSuccess,
233
+ lastError,
234
+ };
235
+ });
106
236
 
107
- buildReport(connectionStatus: any, config: any, stats: any, toolGroups: any) {
108
- const report = {
109
- available: true,
110
- connected: connectionStatus.connected,
111
- apiVersion: connectionStatus.apiVersion,
237
+ const available = toolStatuses.filter(t => t.status === "working").length;
238
+ const failed = toolStatuses.filter(t => t.status === "error").length;
239
+
240
+ tools[group] = {
241
+ enabled: toolNames.length,
242
+ available,
243
+ failed,
244
+ tools: toolStatuses,
245
+ };
246
+ }
247
+
248
+ return {
249
+ connection,
112
250
  config,
113
251
  stats,
114
- tools: toolGroups,
252
+ tools,
253
+ recentCalls,
254
+ issues: this.getIssues(),
115
255
  };
116
- return report;
117
256
  }
118
257
 
119
- static formatReport(report: any): string {
120
- return JSON.stringify(report, null, 2);
258
+ /**
259
+ * Format status report for CLI display
260
+ */
261
+ static formatReport(report: StatusReport): string {
262
+ const lines: string[] = [];
263
+
264
+ // Header
265
+ lines.push("");
266
+ lines.push("MemoryRelay Plugin Status");
267
+ lines.push("━".repeat(50));
268
+ lines.push("");
269
+
270
+ // Connection
271
+ lines.push("CONNECTION");
272
+ const connSymbol = report.connection.status === "connected" ? "✓" : "✗";
273
+ lines.push(` Status: ${connSymbol} ${report.connection.status}`);
274
+ lines.push(` Endpoint: ${report.connection.endpoint}`);
275
+ lines.push(` Response Time: ${report.connection.responseTime}ms`);
276
+ lines.push(` Last Check: ${new Date(report.connection.lastCheck).toLocaleString()}`);
277
+ lines.push("");
278
+
279
+ // Configuration
280
+ lines.push("CONFIGURATION");
281
+ lines.push(` Agent ID: ${report.config.agentId}`);
282
+ const recallStatus = report.config.autoRecall
283
+ ? `✓ Enabled (limit: ${report.config.recallLimit}, threshold: ${report.config.recallThreshold})`
284
+ : "✗ Disabled";
285
+ lines.push(` Auto-Recall: ${recallStatus}`);
286
+ lines.push(` Auto-Capture: ${report.config.autoCapture ? "✓ Enabled" : "✗ Disabled"}`);
287
+ if (report.config.defaultProject) {
288
+ lines.push(` Default Project: ${report.config.defaultProject}`);
289
+ }
290
+ lines.push("");
291
+
292
+ // Memory Statistics
293
+ lines.push("MEMORY STATISTICS");
294
+ lines.push(` Total Memories: ${report.stats.total_memories}`);
295
+ if (report.stats.memories_today !== undefined) {
296
+ lines.push(` Today: ${report.stats.memories_today}`);
297
+ }
298
+ if (report.stats.last_stored) {
299
+ const lastStored = new Date(report.stats.last_stored);
300
+ const ago = this.formatTimeAgo(lastStored);
301
+ lines.push(` Last Stored: ${ago}`);
302
+ }
303
+ if (report.stats.search_count_24h !== undefined) {
304
+ lines.push(` Searches (24h): ${report.stats.search_count_24h}`);
305
+ }
306
+ lines.push("");
307
+
308
+ // Tools Status
309
+ const totalEnabled = Object.values(report.tools).reduce((sum, g) => sum + g.enabled, 0);
310
+ const totalAvailable = Object.values(report.tools).reduce((sum, g) => sum + g.available, 0);
311
+ lines.push(`TOOLS STATUS (${totalAvailable}/${totalEnabled} working)`);
312
+
313
+ for (const [groupName, group] of Object.entries(report.tools)) {
314
+ const symbol = group.failed === 0 ? "✓" : group.failed === group.enabled ? "✗" : "⚠";
315
+ const label = groupName.charAt(0).toUpperCase() + groupName.slice(1);
316
+ lines.push(` ${symbol} ${label}: ${group.available}/${group.enabled} working`);
317
+
318
+ // Show failed tools
319
+ const failedTools = group.tools.filter(t => t.status === "error");
320
+ for (const tool of failedTools) {
321
+ lines.push(` ✗ ${tool.name} (${tool.error})`);
322
+ }
323
+ }
324
+ lines.push("");
325
+
326
+ // Recent Activity
327
+ if (report.recentCalls.length > 0) {
328
+ lines.push(`RECENT ACTIVITY (last ${report.recentCalls.length} calls)`);
329
+ for (const call of report.recentCalls.reverse()) {
330
+ const time = new Date(call.timestamp).toLocaleTimeString();
331
+ const status = call.status === "success" ? "✓" : "✗";
332
+ const duration = `${call.duration}ms`;
333
+ lines.push(` ${time} ${call.tool.padEnd(18)} ${duration.padStart(6)} ${status}`);
334
+ }
335
+ lines.push("");
336
+ }
337
+
338
+ // Known Issues
339
+ if (report.issues.length > 0) {
340
+ lines.push(`KNOWN ISSUES (${report.issues.length})`);
341
+ for (const issue of report.issues) {
342
+ const since = this.formatTimeAgo(new Date(issue.since));
343
+ lines.push(` ⚠ ${issue.tool} - ${issue.error} (since ${since})`);
344
+ }
345
+ lines.push("");
346
+ }
347
+
348
+ // Footer
349
+ lines.push("For detailed logs, run: openclaw memoryrelay logs");
350
+ lines.push("For troubleshooting: https://github.com/MemoryRelay/api/issues/213");
351
+ lines.push("");
352
+
353
+ return lines.join("\n");
354
+ }
355
+
356
+ /**
357
+ * Format time ago string
358
+ */
359
+ private static formatTimeAgo(date: Date): string {
360
+ const seconds = Math.floor((Date.now() - date.getTime()) / 1000);
361
+
362
+ if (seconds < 60) return `${seconds} seconds ago`;
363
+ if (seconds < 3600) return `${Math.floor(seconds / 60)} minutes ago`;
364
+ if (seconds < 86400) return `${Math.floor(seconds / 3600)} hours ago`;
365
+ return `${Math.floor(seconds / 86400)} days ago`;
366
+ }
367
+
368
+ /**
369
+ * Format compact status (for inline display)
370
+ */
371
+ static formatCompact(report: StatusReport): string {
372
+ const totalEnabled = Object.values(report.tools).reduce((sum, g) => sum + g.enabled, 0);
373
+ const totalAvailable = Object.values(report.tools).reduce((sum, g) => sum + g.available, 0);
374
+ const symbol = report.connection.status === "connected" ? "✓" : "✗";
375
+
376
+ return `MemoryRelay: ${symbol} ${report.connection.status}, ${totalAvailable}/${totalEnabled} tools working`;
121
377
  }
122
378
  }
123
379
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memoryrelay/plugin-memoryrelay-ai",
3
- "version": "0.11.2",
3
+ "version": "0.11.4",
4
4
  "description": "OpenClaw memory plugin for MemoryRelay API - sessions, decisions, patterns, projects & semantic search",
5
5
  "type": "module",
6
6
  "main": "index.ts",