Skip to content

Commit f93148a

Browse files
authored
Merge pull request #57 from supermemoryai/codex/add-auto-update-notice
add auto update notice
2 parents 1dca7e3 + 060911b commit f93148a

4 files changed

Lines changed: 91 additions & 0 deletions

File tree

index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@ import { parseConfig, supermemoryConfigSchema } from "./config.ts"
99
import { buildCaptureHandler } from "./hooks/capture.ts"
1010
import { buildRecallHandler } from "./hooks/recall.ts"
1111
import { initLogger } from "./logger.ts"
12+
import { checkNpmUpdate, formatUpdateNotice } from "./lib/version-check.ts"
1213
import { buildMemoryRuntime, buildPromptSection } from "./runtime.ts"
1314
import { registerForgetTool } from "./tools/forget.ts"
1415
import { registerProfileTool } from "./tools/profile.ts"
1516
import { registerSearchTool } from "./tools/search.ts"
1617
import { registerStoreTool } from "./tools/store.ts"
1718

19+
const PLUGIN_VERSION = "2.1.14"
20+
const UPDATE_COMMAND = "openclaw plugins install @supermemory/openclaw-supermemory"
21+
1822
try {
1923
const stateDir =
2024
process.env.OPENCLAW_STATE_DIR || path.join(os.homedir(), ".openclaw")
@@ -100,6 +104,13 @@ export default {
100104
id: "openclaw-supermemory",
101105
start: () => {
102106
api.logger.info("supermemory: connected")
107+
void checkNpmUpdate(
108+
"@supermemory/openclaw-supermemory",
109+
PLUGIN_VERSION,
110+
UPDATE_COMMAND,
111+
).then((info) => {
112+
if (info) api.logger.info(formatUpdateNotice(info))
113+
})
103114
},
104115
stop: () => {
105116
api.logger.info("supermemory: stopped")

lib/version-check.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
const NPM_REGISTRY_URL = "https://registry.npmjs.org";
2+
const CHECK_TIMEOUT_MS = 3000;
3+
4+
export interface UpdateInfo {
5+
currentVersion: string
6+
latestVersion: string
7+
updateCommand: string
8+
}
9+
10+
function parseVersion(
11+
version: string,
12+
): { parts: number[]; prerelease: string | null } | null {
13+
const normalized = version.trim().replace(/^v/i, "")
14+
const match = normalized.match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/)
15+
if (!match) return null
16+
17+
return {
18+
parts: [Number(match[1]), Number(match[2]), Number(match[3])],
19+
prerelease: match[4] ?? null,
20+
}
21+
}
22+
23+
function isVersionNewer(latestVersion: string, currentVersion: string): boolean {
24+
const latest = parseVersion(latestVersion)
25+
const current = parseVersion(currentVersion)
26+
if (!latest || !current) return latestVersion !== currentVersion
27+
28+
for (let i = 0; i < 3; i++) {
29+
const latestPart = latest.parts[i] ?? 0
30+
const currentPart = current.parts[i] ?? 0
31+
if (latestPart > currentPart) return true
32+
if (latestPart < currentPart) return false
33+
}
34+
35+
if (!latest.prerelease && current.prerelease) return true
36+
if (latest.prerelease && !current.prerelease) return false
37+
return latest.prerelease !== current.prerelease && latest.prerelease !== null
38+
}
39+
40+
export async function checkNpmUpdate(
41+
packageName: string,
42+
currentVersion: string,
43+
updateCommand: string,
44+
): Promise<UpdateInfo | null> {
45+
const controller = new AbortController()
46+
const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS)
47+
48+
try {
49+
const encodedPackage = packageName.startsWith("@")
50+
? packageName.replace("/", "%2F")
51+
: encodeURIComponent(packageName)
52+
const response = await fetch(`${NPM_REGISTRY_URL}/${encodedPackage}/latest`, {
53+
signal: controller.signal,
54+
})
55+
if (!response.ok) return null
56+
57+
const data = (await response.json()) as { version?: unknown }
58+
const latestVersion = typeof data.version === "string" ? data.version : null
59+
if (!latestVersion || !isVersionNewer(latestVersion, currentVersion)) {
60+
return null
61+
}
62+
63+
return { currentVersion, latestVersion, updateCommand }
64+
} catch {
65+
return null
66+
} finally {
67+
clearTimeout(timeout)
68+
}
69+
}
70+
71+
export function formatUpdateNotice(info: UpdateInfo): string {
72+
return [
73+
"supermemory: update available",
74+
`current: v${info.currentVersion}`,
75+
`latest: v${info.latestVersion}`,
76+
`run: ${info.updateCommand}`,
77+
].join(" | ")
78+
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"memory.ts",
2222
"runtime.ts",
2323
"types",
24+
"lib/version-check.ts",
2425
"lib/validate.d.ts",
2526
"lib/validate.js",
2627
"dist"

tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"hooks/*.ts",
1919
"commands/*.ts",
2020
"types/*.d.ts",
21+
"lib/*.ts",
2122
"lib/*.d.ts"
2223
],
2324
"exclude": ["node_modules", "dist"]

0 commit comments

Comments
 (0)