From f16e8062e13910b2fd0268d1b6b94ec730d6fea7 Mon Sep 17 00:00:00 2001 From: paisley <8197966+su8su@users.noreply.github.com> Date: Sat, 21 Mar 2026 21:16:50 +0800 Subject: [PATCH] fix: add fsPath prefix for Windows Unicode paths in config-sync plugin copy (#612) --- electron/gateway/config-sync.ts | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/electron/gateway/config-sync.ts b/electron/gateway/config-sync.ts index a866164b1..77ee0717f 100644 --- a/electron/gateway/config-sync.ts +++ b/electron/gateway/config-sync.ts @@ -3,6 +3,18 @@ import path from 'path'; import { existsSync, readFileSync, cpSync, mkdirSync, rmSync } from 'fs'; import { homedir } from 'os'; import { join } from 'path'; + +function fsPath(filePath: string): string { + if (process.platform !== 'win32') return filePath; + if (!filePath) return filePath; + if (filePath.startsWith('\\\\?\\')) return filePath; + const windowsPath = filePath.replace(/\//g, '\\'); + if (!path.win32.isAbsolute(windowsPath)) return windowsPath; + if (windowsPath.startsWith('\\\\')) { + return `\\\\?\\UNC\\${windowsPath.slice(2)}`; + } + return `\\\\?\\${windowsPath}`; +} import { getAllSettings } from '../utils/store'; import { getApiKey, getDefaultProvider, getProvider } from '../utils/secure-storage'; import { getProviderEnvVar, getKeyableProviderTypes } from '../utils/provider-registry'; @@ -40,7 +52,7 @@ const CHANNEL_PLUGIN_MAP: Record = function readPluginVersion(pkgJsonPath: string): string | null { try { - const raw = readFileSync(pkgJsonPath, 'utf-8'); + const raw = readFileSync(fsPath(pkgJsonPath), 'utf-8'); const parsed = JSON.parse(raw) as { version?: string }; return parsed.version ?? null; } catch { @@ -74,12 +86,12 @@ function ensureConfiguredPluginsUpgraded(configuredChannels: string[]): void { const targetDir = join(homedir(), '.openclaw', 'extensions', dirName); const targetManifest = join(targetDir, 'openclaw.plugin.json'); - const isInstalled = existsSync(targetManifest); + const isInstalled = existsSync(fsPath(targetManifest)); const installedVersion = isInstalled ? readPluginVersion(join(targetDir, 'package.json')) : null; // Try bundled sources first (packaged mode or if bundle-plugins was run) const bundledSources = buildBundledPluginSources(dirName); - const bundledDir = bundledSources.find((dir) => existsSync(join(dir, 'openclaw.plugin.json'))); + const bundledDir = bundledSources.find((dir) => existsSync(fsPath(join(dir, 'openclaw.plugin.json')))); if (bundledDir) { const sourceVersion = readPluginVersion(join(bundledDir, 'package.json')); @@ -87,9 +99,9 @@ function ensureConfiguredPluginsUpgraded(configuredChannels: string[]): void { if (!isInstalled || (sourceVersion && installedVersion && sourceVersion !== installedVersion)) { logger.info(`[plugin] ${isInstalled ? 'Auto-upgrading' : 'Installing'} ${channelType} plugin${isInstalled ? `: ${installedVersion} → ${sourceVersion}` : `: ${sourceVersion}`} (bundled)`); try { - mkdirSync(join(homedir(), '.openclaw', 'extensions'), { recursive: true }); - rmSync(targetDir, { recursive: true, force: true }); - cpSync(bundledDir, targetDir, { recursive: true, dereference: true }); + mkdirSync(fsPath(join(homedir(), '.openclaw', 'extensions')), { recursive: true }); + rmSync(fsPath(targetDir), { recursive: true, force: true }); + cpSync(fsPath(bundledDir), fsPath(targetDir), { recursive: true, dereference: true }); fixupPluginManifest(targetDir); } catch (err) { logger.warn(`[plugin] Failed to ${isInstalled ? 'auto-upgrade' : 'install'} ${channelType} plugin:`, err); @@ -101,7 +113,7 @@ function ensureConfiguredPluginsUpgraded(configuredChannels: string[]): void { // Dev mode fallback: copy from node_modules/ with pnpm dep resolution if (!app.isPackaged) { const npmPkgPath = join(process.cwd(), 'node_modules', ...npmName.split('/')); - if (!existsSync(join(npmPkgPath, 'openclaw.plugin.json'))) continue; + if (!existsSync(fsPath(join(npmPkgPath, 'openclaw.plugin.json')))) continue; const sourceVersion = readPluginVersion(join(npmPkgPath, 'package.json')); if (!sourceVersion) continue; // Skip only if installed AND same version @@ -109,7 +121,7 @@ function ensureConfiguredPluginsUpgraded(configuredChannels: string[]): void { logger.info(`[plugin] ${isInstalled ? 'Auto-upgrading' : 'Installing'} ${channelType} plugin${isInstalled ? `: ${installedVersion} → ${sourceVersion}` : `: ${sourceVersion}`} (dev/node_modules)`); try { - mkdirSync(join(homedir(), '.openclaw', 'extensions'), { recursive: true }); + mkdirSync(fsPath(join(homedir(), '.openclaw', 'extensions')), { recursive: true }); copyPluginFromNodeModules(npmPkgPath, targetDir, npmName); fixupPluginManifest(targetDir); } catch (err) {