From b9efd01c57532329e25a5f786704405c47d87db6 Mon Sep 17 00:00:00 2001 From: asorry75 Date: Wed, 5 Aug 2026 17:28:52 +0800 Subject: [PATCH 1/2] fix(bridge): use os.homedir() for PID file path on Windows process.env.HOME is not set on Windows (USERPROFILE is used instead), so pidFilePath() fell back to '/tmp' which Node resolves relative to the current drive root. Every bridge/daemon start on Windows then created a stray :\tmp\.hermes\memos-plugin\daemon\bridge.pid folder on whichever drive the process happened to run from, and the singleton guard could not see PID files written from other drives (e.g. install.ps1 from D: vs daemon_manager from C:), allowing multiple daemons to fight over the viewer port. Replace the fallback with os.homedir(), which resolves correctly on Windows, POSIX, and macOS alike. Fixes stray folder creation and restores cross-entry singleton protection. --- apps/memos-local-plugin/bridge.mts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/memos-local-plugin/bridge.mts b/apps/memos-local-plugin/bridge.mts index 2d967c597..217c8b904 100644 --- a/apps/memos-local-plugin/bridge.mts +++ b/apps/memos-local-plugin/bridge.mts @@ -30,6 +30,7 @@ */ import * as childProcess from "node:child_process"; import * as fs from "node:fs"; +import { homedir } from "node:os"; import * as path from "node:path"; import { fileURLToPath } from "node:url"; @@ -81,7 +82,7 @@ const PID_FILENAME = "bridge.pid"; function pidFilePath(agent: string): string { const agentHome = agent === "hermes" ? ".hermes" : ".openclaw"; return path.join( - process.env.HOME ?? "/tmp", + homedir(), agentHome, "memos-plugin", "daemon", From d2d9b9fd1f9f16453128dd1b8c4129c6a8f3e8f7 Mon Sep 17 00:00:00 2001 From: jiachengzhen Date: Fri, 7 Aug 2026 02:08:25 +0800 Subject: [PATCH 2/2] fix(bridge): align PID home across entrypoints --- apps/memos-local-plugin/bridge.cts | 4 +++- .../tests/unit/bridge/pid-file-path.test.ts | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 apps/memos-local-plugin/tests/unit/bridge/pid-file-path.test.ts diff --git a/apps/memos-local-plugin/bridge.cts b/apps/memos-local-plugin/bridge.cts index acc1ccb29..9a2373e57 100644 --- a/apps/memos-local-plugin/bridge.cts +++ b/apps/memos-local-plugin/bridge.cts @@ -29,6 +29,8 @@ const path = require("node:path") as typeof import("node:path"); // eslint-disable-next-line @typescript-eslint/no-require-imports const fs = require("node:fs") as typeof import("node:fs"); // eslint-disable-next-line @typescript-eslint/no-require-imports +const { homedir } = require("node:os") as typeof import("node:os"); +// eslint-disable-next-line @typescript-eslint/no-require-imports const childProcess = require("node:child_process") as typeof import("node:child_process"); // eslint-disable-next-line @typescript-eslint/no-require-imports const url = require("node:url") as typeof import("node:url"); @@ -95,7 +97,7 @@ const STDIO_PID_FILENAME = "bridge-stdio.pid"; function pidFilePath(agent: string, filename: string = PID_FILENAME): string { const agentHome = agent === "hermes" ? ".hermes" : ".openclaw"; return path.join( - process.env.HOME ?? "/tmp", + homedir(), agentHome, "memos-plugin", "daemon", diff --git a/apps/memos-local-plugin/tests/unit/bridge/pid-file-path.test.ts b/apps/memos-local-plugin/tests/unit/bridge/pid-file-path.test.ts new file mode 100644 index 000000000..4224ba067 --- /dev/null +++ b/apps/memos-local-plugin/tests/unit/bridge/pid-file-path.test.ts @@ -0,0 +1,21 @@ +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; + +import { describe, expect, it } from "vitest"; + +describe("bridge PID file path", () => { + for (const entry of ["bridge.cts", "bridge.mts"]) { + it(`${entry} resolves the PID directory from the OS home`, () => { + const source = readFileSync(resolve(entry), "utf8"); + const start = source.indexOf("function pidFilePath"); + const end = source.indexOf("function readPidFile", start); + + expect(start, `${entry}: pidFilePath() not found`).toBeGreaterThanOrEqual(0); + expect(end, `${entry}: readPidFile() not found`).toBeGreaterThan(start); + + const pidFilePathSource = source.slice(start, end); + expect(pidFilePathSource).toMatch(/\bhomedir\(\)/); + expect(pidFilePathSource).not.toMatch(/process\.env\.HOME|["']\/tmp["']/); + }); + } +});