diff --git a/src-tauri/src/commands/messaging.rs b/src-tauri/src/commands/messaging.rs index 11dd6c7..854917c 100644 --- a/src-tauri/src/commands/messaging.rs +++ b/src-tauri/src/commands/messaging.rs @@ -1090,12 +1090,66 @@ pub async fn check_weixin_plugin_status() -> Result { _ => false, }; + // 兼容性检查:检测插件是否能在当前 OpenClaw 版本下正常加载 + let mut compatible = true; + let mut compat_error = String::new(); + if installed { + // 检查插件引用的 SDK 模块是否存在(channel-config-schema 是 2026.3.14+ 新增的) + if let Some(cli_path) = crate::utils::resolve_openclaw_cli_path() { + let cli_dir = std::path::Path::new(&cli_path) + .parent() + .and_then(|p| p.parent()) + .unwrap_or(std::path::Path::new("")); + let sdk_path = cli_dir + .join("dist") + .join("plugin-sdk") + .join("root-alias.cjs") + .join("channel-config-schema.js"); + if !sdk_path.exists() { + // 也检查 npm 全局路径 + let npm_sdk_exists = { + #[cfg(target_os = "windows")] + { + std::env::var("APPDATA") + .ok() + .map(|appdata| { + let base = std::path::PathBuf::from(appdata) + .join("npm") + .join("node_modules"); + ["openclaw", "@qingchencloud/openclaw-zh"] + .iter() + .any(|pkg| { + base.join(pkg) + .join("dist") + .join("plugin-sdk") + .join("root-alias.cjs") + .join("channel-config-schema.js") + .exists() + }) + }) + .unwrap_or(false) + } + #[cfg(not(target_os = "windows"))] + { + false + } + }; + if !npm_sdk_exists { + compatible = false; + compat_error = "插件版本与当前 OpenClaw 不兼容(缺少 channel-config-schema 模块),请点击「一键安装插件」重新安装兼容版本".to_string(); + } + } + } + } + Ok(json!({ "installed": installed, "installedVersion": installed_version, "latestVersion": latest_version, "updateAvailable": update_available, "extensionDir": ext_dir.to_string_lossy(), + "compatible": compatible, + "compatError": compat_error, })) } diff --git a/src/pages/channels.js b/src/pages/channels.js index 08d9f4c..d9c8fa1 100644 --- a/src/pages/channels.js +++ b/src/pages/channels.js @@ -1325,7 +1325,15 @@ async function openConfigDialog(pid, page, state, accountId) { if (!s) { statusEl.textContent = t('channels.pluginStatusFailed'); return } const parts = [] const installBtn = modal.querySelector('[data-channel-action="install"]') - if (s.installed) { + if (s.installed && s.compatible === false) { + parts.push(`⚠ ${t('channels.pluginIncompatible') || '插件版本不兼容'}`) + parts.push(`${t('channels.version')} ${s.installedVersion || '?'}`) + parts.push(`
${s.compatError || '请点击「一键安装插件」重新安装兼容版本'}`) + if (installBtn) { + installBtn.textContent = t('channels.reinstallCompatible') || '重新安装兼容版本' + installBtn.style.background = 'var(--error)' + } + } else if (s.installed) { parts.push(`● ${t('channels.pluginInstalled')}`) parts.push(`${t('channels.version')} ${s.installedVersion || t('channels.unknown')}`) if (s.updateAvailable && s.latestVersion) {