Upgrade openclaw to 4.1 (#742)
This commit is contained in:
committed by
GitHub
Unverified
parent
5a3da41562
commit
06266cb4d2
@@ -24,7 +24,6 @@ import {
|
||||
import {
|
||||
ensureDingTalkPluginInstalled,
|
||||
ensureFeishuPluginInstalled,
|
||||
ensureQQBotPluginInstalled,
|
||||
ensureWeChatPluginInstalled,
|
||||
ensureWeComPluginInstalled,
|
||||
} from '../../utils/plugin-install';
|
||||
@@ -1198,13 +1197,7 @@ export async function handleChannelRoutes(
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (storedChannelType === 'qqbot') {
|
||||
const installResult = await ensureQQBotPluginInstalled();
|
||||
if (!installResult.installed) {
|
||||
sendJson(res, 500, { success: false, error: installResult.warning || 'QQ Bot plugin install failed' });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// QQBot is a built-in channel since OpenClaw 3.31 — no plugin install needed
|
||||
if (storedChannelType === 'feishu') {
|
||||
const installResult = await ensureFeishuPluginInstalled();
|
||||
if (!installResult.installed) {
|
||||
|
||||
@@ -49,7 +49,7 @@ const CHANNEL_PLUGIN_MAP: Record<string, { dirName: string; npmName: string }> =
|
||||
dingtalk: { dirName: 'dingtalk', npmName: '@soimy/dingtalk' },
|
||||
wecom: { dirName: 'wecom', npmName: '@wecom/wecom-openclaw-plugin' },
|
||||
feishu: { dirName: 'feishu-openclaw-plugin', npmName: '@larksuite/openclaw-lark' },
|
||||
qqbot: { dirName: 'qqbot', npmName: '@tencent-connect/openclaw-qqbot' },
|
||||
|
||||
'openclaw-weixin': { dirName: 'openclaw-weixin', npmName: '@tencent-weixin/openclaw-weixin' },
|
||||
};
|
||||
|
||||
@@ -59,7 +59,7 @@ const CHANNEL_PLUGIN_MAP: Record<string, { dirName: string; npmName: string }> =
|
||||
* ~/.openclaw/extensions/, the broken copy overrides the working built-in
|
||||
* plugin and must be removed.
|
||||
*/
|
||||
const BUILTIN_CHANNEL_EXTENSIONS = ['discord', 'telegram'];
|
||||
const BUILTIN_CHANNEL_EXTENSIONS = ['discord', 'telegram', 'qqbot'];
|
||||
|
||||
function cleanupStaleBuiltInExtensions(): void {
|
||||
for (const ext of BUILTIN_CHANNEL_EXTENSIONS) {
|
||||
@@ -208,7 +208,7 @@ export async function syncGatewayConfigBeforeLaunch(
|
||||
pluginIdToChannel[info.dirName] = channelType;
|
||||
}
|
||||
// Known manifest IDs that differ from their dirName/channelType
|
||||
pluginIdToChannel['openclaw-qqbot'] = 'qqbot';
|
||||
|
||||
pluginIdToChannel['openclaw-lark'] = 'feishu';
|
||||
pluginIdToChannel['feishu-openclaw-plugin'] = 'feishu';
|
||||
|
||||
|
||||
@@ -372,8 +372,9 @@ async function initialize(): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
// Pre-deploy/upgrade bundled OpenClaw plugins (dingtalk, wecom, qqbot, feishu, wechat)
|
||||
// Pre-deploy/upgrade bundled OpenClaw plugins (dingtalk, wecom, feishu, wechat)
|
||||
// to ~/.openclaw/extensions/ so they are always up-to-date after an app update.
|
||||
// Note: qqbot was moved to a built-in channel in OpenClaw 3.31.
|
||||
if (!isE2EMode) {
|
||||
void ensureAllBundledPluginsInstalled().catch((error) => {
|
||||
logger.warn('Failed to install/upgrade bundled plugins:', error);
|
||||
|
||||
@@ -37,7 +37,6 @@ import { checkUvInstalled, installUv, setupManagedPython } from '../utils/uv-set
|
||||
import {
|
||||
ensureDingTalkPluginInstalled,
|
||||
ensureFeishuPluginInstalled,
|
||||
ensureQQBotPluginInstalled,
|
||||
ensureWeComPluginInstalled,
|
||||
} from '../utils/plugin-install';
|
||||
import { updateSkillConfig, getSkillConfig, getAllSkillConfigs } from '../utils/skill-config';
|
||||
@@ -1498,22 +1497,7 @@ function registerOpenClawHandlers(gatewayManager: GatewayManager): void {
|
||||
warning: installResult.warning,
|
||||
};
|
||||
}
|
||||
if (channelType === 'qqbot') {
|
||||
const installResult = await ensureQQBotPluginInstalled();
|
||||
if (!installResult.installed) {
|
||||
return {
|
||||
success: false,
|
||||
error: installResult.warning || 'QQ Bot plugin install failed',
|
||||
};
|
||||
}
|
||||
await saveChannelConfig(channelType, config);
|
||||
scheduleGatewayChannelSaveRefresh(channelType, `channel:saveConfig (${channelType})`);
|
||||
return {
|
||||
success: true,
|
||||
pluginInstalled: installResult.installed,
|
||||
warning: installResult.warning,
|
||||
};
|
||||
}
|
||||
// QQBot is a built-in channel since OpenClaw 3.31 — no plugin install needed
|
||||
if (channelType === 'feishu') {
|
||||
const installResult = await ensureFeishuPluginInstalled();
|
||||
if (!installResult.installed) {
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
const OPENCLAW_DIR = join(homedir(), '.openclaw');
|
||||
const CONFIG_FILE = join(OPENCLAW_DIR, 'openclaw.json');
|
||||
const WECOM_PLUGIN_ID = 'wecom';
|
||||
const QQBOT_PLUGIN_ID = 'openclaw-qqbot';
|
||||
// Note: QQBot is a built-in channel since OpenClaw 3.31 — no plugin ID needed.
|
||||
const WECHAT_PLUGIN_ID = OPENCLAW_WECHAT_CHANNEL_TYPE;
|
||||
const FEISHU_PLUGIN_ID_CANDIDATES = ['openclaw-lark', 'feishu-openclaw-plugin'] as const;
|
||||
const DEFAULT_ACCOUNT_ID = 'default';
|
||||
@@ -48,6 +48,7 @@ const BUILTIN_CHANNEL_IDS = new Set([
|
||||
'msteams',
|
||||
'googlechat',
|
||||
'mattermost',
|
||||
'qqbot',
|
||||
]);
|
||||
|
||||
// Unique credential key per channel type – used for duplicate bot detection.
|
||||
@@ -464,37 +465,7 @@ async function ensurePluginAllowlist(currentConfig: OpenClawConfig, channelType:
|
||||
}
|
||||
}
|
||||
|
||||
if (channelType === 'qqbot') {
|
||||
if (!currentConfig.plugins) {
|
||||
currentConfig.plugins = {
|
||||
allow: [QQBOT_PLUGIN_ID],
|
||||
enabled: true,
|
||||
entries: {
|
||||
[QQBOT_PLUGIN_ID]: { enabled: true }
|
||||
}
|
||||
};
|
||||
} else {
|
||||
currentConfig.plugins.enabled = true;
|
||||
const allow: string[] = Array.isArray(currentConfig.plugins.allow)
|
||||
? (currentConfig.plugins.allow as string[])
|
||||
: [];
|
||||
// Normalize: remove bare 'qqbot' and ensure the actual manifest ID is present.
|
||||
const normalizedAllow = allow.filter((pluginId) => pluginId !== 'qqbot');
|
||||
if (!normalizedAllow.includes(QQBOT_PLUGIN_ID)) {
|
||||
currentConfig.plugins.allow = [...normalizedAllow, QQBOT_PLUGIN_ID];
|
||||
} else if (normalizedAllow.length !== allow.length) {
|
||||
currentConfig.plugins.allow = normalizedAllow;
|
||||
}
|
||||
|
||||
if (!currentConfig.plugins.entries) {
|
||||
currentConfig.plugins.entries = {};
|
||||
}
|
||||
if (!currentConfig.plugins.entries[QQBOT_PLUGIN_ID]) {
|
||||
currentConfig.plugins.entries[QQBOT_PLUGIN_ID] = {};
|
||||
}
|
||||
currentConfig.plugins.entries[QQBOT_PLUGIN_ID].enabled = true;
|
||||
}
|
||||
}
|
||||
// Note: QQBot is a built-in channel since OpenClaw 3.31 — no plugin registration needed.
|
||||
|
||||
if (channelType === WECHAT_PLUGIN_ID) {
|
||||
if (!currentConfig.plugins) {
|
||||
|
||||
@@ -222,6 +222,7 @@ const BUILTIN_CHANNEL_IDS = new Set([
|
||||
'msteams',
|
||||
'googlechat',
|
||||
'mattermost',
|
||||
'qqbot',
|
||||
]);
|
||||
const AUTH_PROFILE_PROVIDER_KEY_MAP: Record<string, string> = {
|
||||
'openai-codex': 'openai',
|
||||
@@ -1507,34 +1508,21 @@ export async function sanitizeOpenClawConfig(): Promise<void> {
|
||||
modified = true;
|
||||
}
|
||||
|
||||
// ── qqbot → openclaw-qqbot migration ────────────────────────
|
||||
// The qqbot npm package (@tencent-connect/openclaw-qqbot) declares
|
||||
// id="openclaw-qqbot" in its manifest, but older ClawX versions
|
||||
// wrote bare "qqbot" into plugins.allow. Migrate to the manifest ID
|
||||
// so the Gateway can resolve the plugin correctly.
|
||||
const LEGACY_QQBOT_ID = 'qqbot';
|
||||
const NEW_QQBOT_ID = 'openclaw-qqbot';
|
||||
if (Array.isArray(pluginsObj.allow)) {
|
||||
const allowArr = pluginsObj.allow as string[];
|
||||
const legacyIdx = allowArr.indexOf(LEGACY_QQBOT_ID);
|
||||
if (legacyIdx !== -1) {
|
||||
if (!allowArr.includes(NEW_QQBOT_ID)) {
|
||||
allowArr[legacyIdx] = NEW_QQBOT_ID;
|
||||
} else {
|
||||
allowArr.splice(legacyIdx, 1);
|
||||
}
|
||||
console.log(`[sanitize] Migrated plugins.allow: ${LEGACY_QQBOT_ID} → ${NEW_QQBOT_ID}`);
|
||||
// ── qqbot built-in channel cleanup ──────────────────────────
|
||||
// OpenClaw 3.31 moved qqbot from a third-party plugin to a built-in
|
||||
// channel. Clean up legacy plugin entries (both bare "qqbot" and
|
||||
// manifest-declared "openclaw-qqbot") from plugins.entries.
|
||||
// plugins.allow is left untouched — having openclaw-qqbot there is harmless.
|
||||
// The channel config under channels.qqbot is preserved and works
|
||||
// identically with the built-in channel.
|
||||
const QQBOT_PLUGIN_IDS = ['qqbot', 'openclaw-qqbot'] as const;
|
||||
for (const qqbotId of QQBOT_PLUGIN_IDS) {
|
||||
if (pEntries?.[qqbotId]) {
|
||||
delete pEntries[qqbotId];
|
||||
console.log(`[sanitize] Removed built-in channel plugin from plugins.entries: ${qqbotId}`);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
if (pEntries?.[LEGACY_QQBOT_ID]) {
|
||||
if (!pEntries[NEW_QQBOT_ID]) {
|
||||
pEntries[NEW_QQBOT_ID] = pEntries[LEGACY_QQBOT_ID];
|
||||
}
|
||||
delete pEntries[LEGACY_QQBOT_ID];
|
||||
console.log(`[sanitize] Migrated plugins.entries: ${LEGACY_QQBOT_ID} → ${NEW_QQBOT_ID}`);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
// ── qwen-portal → modelstudio migration ────────────────────
|
||||
// OpenClaw 2026.3.28 deprecated qwen-portal OAuth (portal.qwen.ai)
|
||||
|
||||
@@ -37,7 +37,7 @@ const _discordSdk = requireOpenClawSdk('openclaw/plugin-sdk/discord') as {
|
||||
normalizeDiscordMessagingTarget: (target: string) => string | undefined;
|
||||
};
|
||||
|
||||
const _telegramSdk = requireOpenClawSdk('openclaw/plugin-sdk/telegram') as {
|
||||
const _telegramSdk = requireOpenClawSdk('openclaw/plugin-sdk/telegram-surface') as {
|
||||
listTelegramDirectoryGroupsFromConfig: (...args: unknown[]) => Promise<unknown[]>;
|
||||
listTelegramDirectoryPeersFromConfig: (...args: unknown[]) => Promise<unknown[]>;
|
||||
normalizeTelegramMessagingTarget: (target: string) => string | undefined;
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
* Shared OpenClaw Plugin Install Utilities
|
||||
*
|
||||
* Provides version-aware install/upgrade logic for bundled OpenClaw plugins
|
||||
* (DingTalk, WeCom, QQBot, Feishu, WeChat). Used both at app startup (to auto-upgrade
|
||||
* (DingTalk, WeCom, Feishu, WeChat). Used both at app startup (to auto-upgrade
|
||||
* stale plugins) and when a user configures a channel.
|
||||
*
|
||||
* Note: QQBot was moved to a built-in channel in OpenClaw 3.31 and is no longer
|
||||
* managed as a plugin.
|
||||
*/
|
||||
import { app } from 'electron';
|
||||
import path from 'node:path';
|
||||
@@ -231,7 +234,7 @@ const PLUGIN_NPM_NAMES: Record<string, string> = {
|
||||
dingtalk: '@soimy/dingtalk',
|
||||
wecom: '@wecom/wecom-openclaw-plugin',
|
||||
'feishu-openclaw-plugin': '@larksuite/openclaw-lark',
|
||||
qqbot: '@tencent-connect/openclaw-qqbot',
|
||||
|
||||
'openclaw-weixin': '@tencent-weixin/openclaw-weixin',
|
||||
};
|
||||
|
||||
@@ -508,9 +511,7 @@ export function ensureFeishuPluginInstalled(): { installed: boolean; warning?: s
|
||||
);
|
||||
}
|
||||
|
||||
export function ensureQQBotPluginInstalled(): { installed: boolean; warning?: string } {
|
||||
return ensurePluginInstalled('qqbot', buildCandidateSources('qqbot'), 'QQ Bot');
|
||||
}
|
||||
|
||||
|
||||
export function ensureWeChatPluginInstalled(): { installed: boolean; warning?: string } {
|
||||
return ensurePluginInstalled('openclaw-weixin', buildCandidateSources('openclaw-weixin'), 'WeChat');
|
||||
@@ -524,7 +525,7 @@ export function ensureWeChatPluginInstalled(): { installed: boolean; warning?: s
|
||||
const ALL_BUNDLED_PLUGINS = [
|
||||
{ fn: ensureDingTalkPluginInstalled, label: 'DingTalk' },
|
||||
{ fn: ensureWeComPluginInstalled, label: 'WeCom' },
|
||||
{ fn: ensureQQBotPluginInstalled, label: 'QQ Bot' },
|
||||
|
||||
{ fn: ensureFeishuPluginInstalled, label: 'Feishu' },
|
||||
{ fn: ensureWeChatPluginInstalled, label: 'WeChat' },
|
||||
] as const;
|
||||
|
||||
Reference in New Issue
Block a user