diff --git a/packages/napcat-onebot/network/plugin-manger.ts b/packages/napcat-onebot/network/plugin-manger.ts index fa5e3350..be10ab89 100644 --- a/packages/napcat-onebot/network/plugin-manger.ts +++ b/packages/napcat-onebot/network/plugin-manger.ts @@ -179,6 +179,9 @@ export class OB11PluginMangerAdapter extends IOB11NetworkAdapter i this.pluginRouters.delete(entry.id); } + // 清理模块缓存 + this.loader.clearCache(entry.pluginPath); + // 重置状态 entry.loaded = false; entry.runtime = { diff --git a/packages/napcat-onebot/network/plugin/loader.ts b/packages/napcat-onebot/network/plugin/loader.ts index 85ab8030..424a8696 100644 --- a/packages/napcat-onebot/network/plugin/loader.ts +++ b/packages/napcat-onebot/network/plugin/loader.ts @@ -1,5 +1,7 @@ import fs from 'fs'; import path from 'path'; +import { createRequire } from 'module'; +const require = createRequire(import.meta.url); import { LogWrapper } from 'napcat-core/helper/log'; import { PluginPackageJson, @@ -295,4 +297,24 @@ export class PluginLoader { return null; } + /** + * 清除插件文件的 require 缓存 + * 用于确保卸载插件时清理 CJS 模块缓存 + */ + clearCache (pluginPath: string): void { + try { + // 规范化路径以确保匹配正确 + const normalizedPluginPath = path.resolve(pluginPath); + + // 遍历缓存并删除属于该插件目录的模块 + Object.keys(require.cache).forEach((id) => { + if (id.startsWith(normalizedPluginPath)) { + delete require.cache[id]; + this.logger.logDebug(`[PluginLoader] Cleared cache for: ${id}`); + } + }); + } catch (e) { + this.logger.logError('[PluginLoader] Error clearing module cache:', e); + } + } } diff --git a/packages/napcat-webui-backend/src/api/PluginStore.ts b/packages/napcat-webui-backend/src/api/PluginStore.ts index e9630321..279d4741 100644 --- a/packages/napcat-webui-backend/src/api/PluginStore.ts +++ b/packages/napcat-webui-backend/src/api/PluginStore.ts @@ -254,11 +254,13 @@ export const InstallPluginFromStoreHandler: RequestHandler = async (req, res) => // 删除临时文件 fs.unlinkSync(tempZipPath); - // 如果 pluginManager 存在,立即注册插件 + // 如果 pluginManager 存在,立即注册或重载插件 const pluginManager = getPluginManager(); if (pluginManager) { - // 检查是否已注册,避免重复注册 - if (!pluginManager.getPluginInfo(id)) { + // 如果插件已存在,则重载以刷新版本信息;否则注册新插件 + if (pluginManager.getPluginInfo(id)) { + await pluginManager.reloadPlugin(id); + } else { await pluginManager.loadPluginById(id); } } @@ -336,11 +338,14 @@ export const InstallPluginFromStoreSSEHandler: RequestHandler = async (req, res) sendProgress('解压完成,正在清理...', 90); fs.unlinkSync(tempZipPath); - // 如果 pluginManager 存在,立即注册插件 + // 如果 pluginManager 存在,立即注册或重载插件 const pluginManager = getPluginManager(); if (pluginManager) { - // 检查是否已注册,避免重复注册 - if (!pluginManager.getPluginInfo(id)) { + // 如果插件已存在,则重载以刷新版本信息;否则注册新插件 + if (pluginManager.getPluginInfo(id)) { + sendProgress('正在刷新插件信息...', 95); + await pluginManager.reloadPlugin(id); + } else { sendProgress('正在注册插件...', 95); await pluginManager.loadPluginById(id); }