From 060911bd9955f1ce254b835a585946b9f34b1cca Mon Sep 17 00:00:00 2001 From: Ishaan Gupta Date: Mon, 8 Jun 2026 15:54:44 +0530 Subject: [PATCH] add auto update notice --- index.ts | 11 +++++++ lib/version-check.ts | 78 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + tsconfig.json | 1 + 4 files changed, 91 insertions(+) create mode 100644 lib/version-check.ts diff --git a/index.ts b/index.ts index 7ac9dfc..9460f63 100644 --- a/index.ts +++ b/index.ts @@ -9,12 +9,16 @@ import { parseConfig, supermemoryConfigSchema } from "./config.ts" import { buildCaptureHandler } from "./hooks/capture.ts" import { buildRecallHandler } from "./hooks/recall.ts" import { initLogger } from "./logger.ts" +import { checkNpmUpdate, formatUpdateNotice } from "./lib/version-check.ts" import { buildMemoryRuntime, buildPromptSection } from "./runtime.ts" import { registerForgetTool } from "./tools/forget.ts" import { registerProfileTool } from "./tools/profile.ts" import { registerSearchTool } from "./tools/search.ts" import { registerStoreTool } from "./tools/store.ts" +const PLUGIN_VERSION = "2.1.14" +const UPDATE_COMMAND = "openclaw plugins install @supermemory/openclaw-supermemory" + try { const stateDir = process.env.OPENCLAW_STATE_DIR || path.join(os.homedir(), ".openclaw") @@ -96,6 +100,13 @@ export default { id: "openclaw-supermemory", start: () => { api.logger.info("supermemory: connected") + void checkNpmUpdate( + "@supermemory/openclaw-supermemory", + PLUGIN_VERSION, + UPDATE_COMMAND, + ).then((info) => { + if (info) api.logger.info(formatUpdateNotice(info)) + }) }, stop: () => { api.logger.info("supermemory: stopped") diff --git a/lib/version-check.ts b/lib/version-check.ts new file mode 100644 index 0000000..80096ce --- /dev/null +++ b/lib/version-check.ts @@ -0,0 +1,78 @@ +const NPM_REGISTRY_URL = "https://registry.npmjs.org"; +const CHECK_TIMEOUT_MS = 3000; + +export interface UpdateInfo { + currentVersion: string + latestVersion: string + updateCommand: string +} + +function parseVersion( + version: string, +): { parts: number[]; prerelease: string | null } | null { + const normalized = version.trim().replace(/^v/i, "") + const match = normalized.match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/) + if (!match) return null + + return { + parts: [Number(match[1]), Number(match[2]), Number(match[3])], + prerelease: match[4] ?? null, + } +} + +function isVersionNewer(latestVersion: string, currentVersion: string): boolean { + const latest = parseVersion(latestVersion) + const current = parseVersion(currentVersion) + if (!latest || !current) return latestVersion !== currentVersion + + for (let i = 0; i < 3; i++) { + const latestPart = latest.parts[i] ?? 0 + const currentPart = current.parts[i] ?? 0 + if (latestPart > currentPart) return true + if (latestPart < currentPart) return false + } + + if (!latest.prerelease && current.prerelease) return true + if (latest.prerelease && !current.prerelease) return false + return latest.prerelease !== current.prerelease && latest.prerelease !== null +} + +export async function checkNpmUpdate( + packageName: string, + currentVersion: string, + updateCommand: string, +): Promise { + const controller = new AbortController() + const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS) + + try { + const encodedPackage = packageName.startsWith("@") + ? packageName.replace("/", "%2F") + : encodeURIComponent(packageName) + const response = await fetch(`${NPM_REGISTRY_URL}/${encodedPackage}/latest`, { + signal: controller.signal, + }) + if (!response.ok) return null + + const data = (await response.json()) as { version?: unknown } + const latestVersion = typeof data.version === "string" ? data.version : null + if (!latestVersion || !isVersionNewer(latestVersion, currentVersion)) { + return null + } + + return { currentVersion, latestVersion, updateCommand } + } catch { + return null + } finally { + clearTimeout(timeout) + } +} + +export function formatUpdateNotice(info: UpdateInfo): string { + return [ + "supermemory: update available", + `current: v${info.currentVersion}`, + `latest: v${info.latestVersion}`, + `run: ${info.updateCommand}`, + ].join(" | ") +} diff --git a/package.json b/package.json index 5d20eb8..d88851c 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "memory.ts", "runtime.ts", "types", + "lib/version-check.ts", "lib/validate.d.ts", "lib/validate.js", "dist" diff --git a/tsconfig.json b/tsconfig.json index f55f8b4..852bfd0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,6 +18,7 @@ "hooks/*.ts", "commands/*.ts", "types/*.d.ts", + "lib/*.ts", "lib/*.d.ts" ], "exclude": ["node_modules", "dist"]