@memtensor/memos-cloud-openclaw-plugin 0.1.8-beta.3 → 0.1.8-beta.5

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.
@@ -2,7 +2,7 @@
2
2
  "id": "memos-cloud-openclaw-plugin",
3
3
  "name": "MemOS Cloud OpenClaw Plugin",
4
4
  "description": "MemOS Cloud recall + add memory via lifecycle hooks",
5
- "version": "0.1.8-beta.3",
5
+ "version": "0.1.8-beta.5",
6
6
  "kind": "lifecycle",
7
7
  "main": "./index.js",
8
8
  "configSchema": {
package/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  USER_QUERY_MARKER,
8
8
  searchMemory,
9
9
  } from "./lib/memos-cloud-api.js";
10
- import { checkUpdate } from "./lib/check-update.js";
10
+ import { startUpdateChecker } from "./lib/check-update.js";
11
11
  let lastCaptureTime = 0;
12
12
  const conversationCounters = new Map();
13
13
  const API_KEY_HELP_URL = "https://memos-dashboard.openmem.net/cn/apikeys/";
@@ -206,8 +206,8 @@ export default {
206
206
  const cfg = buildConfig(api.pluginConfig);
207
207
  const log = api.logger ?? console;
208
208
 
209
- // Call update check asynchronously. The interval control is inside checkUpdate
210
- checkUpdate(log);
209
+ // Start 12-hour background update interval
210
+ startUpdateChecker(log);
211
211
 
212
212
  if (!cfg.envFileStatus?.found) {
213
213
  const searchPaths = cfg.envFileStatus?.searchPaths?.join(", ") ?? ENV_FILE_SEARCH_HINTS.join(", ");
@@ -233,7 +233,6 @@ export default {
233
233
  }
234
234
 
235
235
  api.on("before_agent_start", async (event, ctx) => {
236
- checkUpdate(log);
237
236
  if (!cfg.recallEnabled) return;
238
237
  if (!event?.prompt || event.prompt.length < 3) return;
239
238
  if (!cfg.apiKey) {
@@ -1,13 +1,13 @@
1
1
  import https from "https";
2
2
  import fs from "fs";
3
- import { exec } from "child_process";
4
3
  import path from "path";
5
4
  import { fileURLToPath } from "url";
5
+ import { exec } from "child_process";
6
6
  import os from "os";
7
7
 
8
8
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
9
 
10
- const CHECK_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours
10
+ const CHECK_INTERVAL = 12 * 60 * 60 * 1000; // 12 hours
11
11
  const PLUGIN_NAME = "@memtensor/memos-cloud-openclaw-plugin";
12
12
  const CHECK_FILE = path.join(os.tmpdir(), "memos_openclaw_update_check.json");
13
13
 
@@ -102,17 +102,85 @@ function compareVersions(v1, v2) {
102
102
  return 0;
103
103
  }
104
104
 
105
- export async function checkUpdate(log) {
106
- // Only check for updates when the gateway is starting.
107
- // When starting the gateway, 'gateway' is in process.argv.
108
- log.warn(JSON.stringify(process.argv))
105
+ export function startUpdateChecker(log) {
106
+ // Only start the interval if we are in the gateway
109
107
  const isGateway = process.argv.includes("gateway");
110
-
111
108
  if (!isGateway) {
112
109
  return;
113
110
  }
114
111
 
115
- const now = Date.now();
112
+ const runCheck = async () => {
113
+ // TRULY PREVENT LOOPS: The instant we start a check, record the time BEFORE any network or processing happens.
114
+ // This absolutely guarantees that even if the network hangs, NPM crashes, or openclaw update causes an immediate hot reload,
115
+ // the system has already advanced the 12-hour/1-min clock and will NOT re-enter this function on boot.
116
+ try {
117
+ fs.writeFileSync(CHECK_FILE, JSON.stringify({ time: Date.now() }));
118
+ } catch (e) {
119
+ log.warn?.(`${ANSI.RED}[memos-cloud] Failed to write timestamp file: ${e.message}${ANSI.RESET}`);
120
+ }
121
+
122
+ const currentVersion = getPackageVersion();
123
+ if (!currentVersion) {
124
+ log.warn?.(`${ANSI.RED}[memos-cloud] Could not read current version from package.json${ANSI.RESET}`);
125
+ return;
126
+ }
127
+
128
+ try {
129
+ const latestVersion = await getLatestVersion(log);
130
+
131
+ // Normal version check
132
+ if (compareVersions(latestVersion, currentVersion) <= 0) {
133
+ return;
134
+ }
135
+
136
+ log.info?.(`${ANSI.YELLOW}[memos-cloud] Update available: ${currentVersion} -> ${latestVersion}. Updating in background...${ANSI.RESET}`);
137
+
138
+ let dotCount = 0;
139
+ const progressInterval = setInterval(() => {
140
+ dotCount++;
141
+ const dots = ".".repeat(dotCount % 4);
142
+ log.info?.(`${ANSI.YELLOW}[memos-cloud] Update in progress for memos-cloud-openclaw-plugin${dots}${ANSI.RESET}`);
143
+ }, 5000); // Log every 5 seconds to show it's still alive
144
+
145
+ const cliName = (() => {
146
+ // Check the full path of the entry script (e.g., .../moltbot/bin/index.js) or the executable
147
+ const scriptPath = process.argv[1] ? process.argv[1].toLowerCase() : "";
148
+ const execPath = process.execPath ? process.execPath.toLowerCase() : "";
149
+
150
+ if (scriptPath.includes("moltbot") || execPath.includes("moltbot")) return "moltbot";
151
+ if (scriptPath.includes("clawdbot") || execPath.includes("clawdbot")) return "clawdbot";
152
+ return "openclaw";
153
+ })();
154
+
155
+ exec(`${cliName} plugins update memos-cloud-openclaw-plugin`, (error, stdout, stderr) => {
156
+ clearInterval(progressInterval);
157
+
158
+ const outText = (stdout || "").trim();
159
+ const errText = (stderr || "").trim();
160
+
161
+ if (outText) log.info?.(`${ANSI.CYAN}[${cliName}-cli]${ANSI.RESET}\n${outText}`);
162
+ if (errText) log.warn?.(`${ANSI.RED}[${cliName}-cli]${ANSI.RESET}\n${errText}`);
163
+
164
+ // Wait for a brief moment to let file system sync if needed
165
+ setTimeout(() => {
166
+ const postUpdateVersion = getPackageVersion();
167
+ const actuallyUpdated = (postUpdateVersion === latestVersion) && (postUpdateVersion !== currentVersion);
168
+
169
+ if (error || !actuallyUpdated) {
170
+ const reason = error ? "Command exited with error" : "Version did not change after update command";
171
+ log.warn?.(`${ANSI.RED}[memos-cloud] Auto-update failed (${reason}). Please refer to the CLI logs above, or run manually: ${cliName} plugins update memos-cloud-openclaw-plugin${ANSI.RESET}`);
172
+ } else {
173
+ log.info?.(`${ANSI.GREEN}[memos-cloud] Successfully updated to version ${latestVersion}. Please restart the gateway to apply changes.${ANSI.RESET}`);
174
+ }
175
+ }, 1000); // Small 1-second buffer for file systems
176
+ });
177
+
178
+ } catch (error) {
179
+ log.warn?.(`${ANSI.RED}[memos-cloud] Update check failed entirely: ${error.message}${ANSI.RESET}`);
180
+ }
181
+ };
182
+
183
+ // Check when we last ran
116
184
  let lastCheckTime = 0;
117
185
  try {
118
186
  if (fs.existsSync(CHECK_FILE)) {
@@ -121,77 +189,20 @@ export async function checkUpdate(log) {
121
189
  }
122
190
  } catch (e) {}
123
191
 
124
- if (now - lastCheckTime < CHECK_INTERVAL) {
125
- return;
126
- }
127
-
128
- const currentVersion = getPackageVersion();
129
- if (!currentVersion) {
130
- return;
131
- }
132
-
133
- try {
134
- const latestVersion = await getLatestVersion(log);
135
-
136
- // Normal version check
137
- if (compareVersions(latestVersion, currentVersion) <= 0) {
138
- return;
139
- }
140
-
141
- log.info?.(`${ANSI.YELLOW}[memos-cloud] Update available: ${currentVersion} -> ${latestVersion}. Updating in background...${ANSI.RESET}`);
142
-
143
-
144
- let dotCount = 0;
145
- const progressInterval = setInterval(() => {
146
- dotCount++;
147
- const dots = ".".repeat(dotCount % 4);
148
- log.info?.(`${ANSI.YELLOW}[memos-cloud] Update in progress for memos-cloud-openclaw-plugin${dots}${ANSI.RESET}`);
149
- }, 5000); // Log every 5 seconds to show it's still alive
150
-
151
- const cliName = (() => {
152
- // Check the full path of the entry script (e.g., .../moltbot/bin/index.js) or the executable
153
- const scriptPath = process.argv[1] ? process.argv[1].toLowerCase() : "";
154
- const execPath = process.execPath ? process.execPath.toLowerCase() : "";
155
-
156
- if (scriptPath.includes("moltbot") || execPath.includes("moltbot")) return "moltbot";
157
- if (scriptPath.includes("clawdbot") || execPath.includes("clawdbot")) return "clawdbot";
158
- return "openclaw";
159
- })();
160
-
161
- exec(`${cliName} plugins update memos-cloud-openclaw-plugin`, (error, stdout, stderr) => {
162
- clearInterval(progressInterval);
163
-
164
- const combinedOutput = `${outText} ${errText}`.toLowerCase();
165
- const requiresRestart = combinedOutput.includes("restart") ||
166
- combinedOutput.includes("already at");
167
-
168
- // ONLY write the 24-hour throttle if the CLI actually tells us to restart the gateway
169
- // This is the condition that indicates a loop might happen (because the CLI modified openclaw.json)
170
- // Or if the CLI outputs 'already at', meaning the update was suppressed due to fixed spec.
171
- if (requiresRestart) {
172
- try {
173
- fs.writeFileSync(CHECK_FILE, JSON.stringify({ time: now }));
174
- } catch (e) {}
175
- }
176
-
177
- if (outText) log.info?.(`${ANSI.CYAN}[${cliName}-cli]${ANSI.RESET}\n${outText}`);
178
- if (errText) log.warn?.(`${ANSI.RED}[${cliName}-cli]${ANSI.RESET}\n${errText}`);
179
-
180
- // Wait for a brief moment to let file system sync if needed
181
- setTimeout(() => {
182
- const postUpdateVersion = getPackageVersion();
183
- const actuallyUpdated = (postUpdateVersion === latestVersion) && (postUpdateVersion !== currentVersion);
184
-
185
- if (error || !actuallyUpdated) {
186
- const reason = error ? "Command exited with error" : "Version did not change after update command";
187
- log.warn?.(`${ANSI.RED}[memos-cloud] Auto-update failed (${reason}). Please refer to the CLI logs above, or run manually: ${cliName} plugins update memos-cloud-openclaw-plugin${ANSI.RESET}`);
188
- } else {
189
- log.info?.(`${ANSI.GREEN}[memos-cloud] Successfully updated to version ${latestVersion}. Please restart the gateway to apply changes.${ANSI.RESET}`);
190
- }
191
- }, 1000); // Small 1-second buffer for file systems
192
- });
193
-
194
- } catch (error) {
195
- // Silently handle errors
192
+ const now = Date.now();
193
+ const timeSinceLastCheck = now - lastCheckTime;
194
+
195
+ // If the interval has passed, run it IMMEDIATELY without delay.
196
+ // The immediate file-write at the top of runCheck() will prevent loop scenarios.
197
+ if (timeSinceLastCheck >= CHECK_INTERVAL) {
198
+ runCheck();
199
+ setInterval(runCheck, CHECK_INTERVAL);
200
+ } else {
201
+ // If it hasn't been the full interval yet, wait the remaining time, then trigger interval
202
+ const timeUntilNextCheck = CHECK_INTERVAL - timeSinceLastCheck;
203
+ setTimeout(() => {
204
+ runCheck();
205
+ setInterval(runCheck, CHECK_INTERVAL);
206
+ }, timeUntilNextCheck);
196
207
  }
197
208
  }
@@ -2,7 +2,7 @@
2
2
  "id": "memos-cloud-openclaw-plugin",
3
3
  "name": "MemOS Cloud OpenClaw Plugin",
4
4
  "description": "MemOS Cloud recall + add memory via lifecycle hooks",
5
- "version": "0.1.8-beta.3",
5
+ "version": "0.1.8-beta.5",
6
6
  "kind": "lifecycle",
7
7
  "main": "./index.js",
8
8
  "configSchema": {
@@ -2,7 +2,7 @@
2
2
  "id": "memos-cloud-openclaw-plugin",
3
3
  "name": "MemOS Cloud OpenClaw Plugin",
4
4
  "description": "MemOS Cloud recall + add memory via lifecycle hooks",
5
- "version": "0.1.8-beta.3",
5
+ "version": "0.1.8-beta.5",
6
6
  "kind": "lifecycle",
7
7
  "main": "./index.js",
8
8
  "configSchema": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memtensor/memos-cloud-openclaw-plugin",
3
- "version": "0.1.8-beta.3",
3
+ "version": "0.1.8-beta.5",
4
4
  "description": "OpenClaw lifecycle plugin for MemOS Cloud (add + recall memory)",
5
5
  "scripts": {
6
6
  "sync-version": "node scripts/sync-version.js",