From 5b8a35391d7a09a467f6fc0759f34c957ee68fe7 Mon Sep 17 00:00:00 2001 From: Haze <709547807@qq.com> Date: Mon, 13 Apr 2026 17:39:48 +0800 Subject: [PATCH] Remove @larksuite/openclaw-lark dependency and related plugin installation logic, as Feishu is now a built-in extension since OpenClaw 2026.4.11. Update relevant code and documentation to reflect this change. --- electron/api/routes/channels.ts | 10 +------ electron/gateway/config-sync.ts | 8 +----- electron/main/ipc-handlers.ts | 19 +------------ electron/utils/channel-config.ts | 2 +- electron/utils/openclaw-auth.ts | 2 +- electron/utils/plugin-install.ts | 14 +--------- package.json | 2 +- pnpm-lock.yaml | 43 ++++------------------------- scripts/after-pack.cjs | 1 - scripts/bundle-openclaw-plugins.mjs | 6 ++-- scripts/bundle-openclaw.mjs | 2 +- tests/unit/channel-routes.test.ts | 1 - 12 files changed, 17 insertions(+), 93 deletions(-) diff --git a/electron/api/routes/channels.ts b/electron/api/routes/channels.ts index 3197d20..1b2a992 100644 --- a/electron/api/routes/channels.ts +++ b/electron/api/routes/channels.ts @@ -25,7 +25,6 @@ import { } from '../../utils/agent-config'; import { ensureDingTalkPluginInstalled, - ensureFeishuPluginInstalled, ensureWeChatPluginInstalled, ensureWeComPluginInstalled, } from '../../utils/plugin-install'; @@ -1349,14 +1348,7 @@ export async function handleChannelRoutes( 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) { - sendJson(res, 500, { success: false, error: installResult.warning || 'Feishu plugin install failed' }); - return true; - } - } + // Feishu is a built-in extension since OpenClaw 2026.4.11 — no plugin install needed if (storedChannelType === OPENCLAW_WECHAT_CHANNEL_TYPE) { const installResult = await ensureWeChatPluginInstalled(); if (!installResult.installed) { diff --git a/electron/gateway/config-sync.ts b/electron/gateway/config-sync.ts index 8d1b142..4fa3f8c 100644 --- a/electron/gateway/config-sync.ts +++ b/electron/gateway/config-sync.ts @@ -48,7 +48,6 @@ export interface GatewayLaunchContext { const CHANNEL_PLUGIN_MAP: Record = { dingtalk: { dirName: 'dingtalk', npmName: '@soimy/dingtalk' }, wecom: { dirName: 'wecom', npmName: '@wecom/wecom-openclaw-plugin' }, - feishu: { dirName: 'feishu-openclaw-plugin', npmName: '@larksuite/openclaw-lark' }, 'openclaw-weixin': { dirName: 'openclaw-weixin', npmName: '@tencent-weixin/openclaw-weixin' }, }; @@ -59,7 +58,7 @@ const CHANNEL_PLUGIN_MAP: Record = * ~/.openclaw/extensions/, the broken copy overrides the working built-in * plugin and must be removed. */ -const BUILTIN_CHANNEL_EXTENSIONS = ['discord', 'telegram', 'qqbot']; +const BUILTIN_CHANNEL_EXTENSIONS = ['discord', 'telegram', 'qqbot', 'feishu-openclaw-plugin']; function cleanupStaleBuiltInExtensions(): void { for (const ext of BUILTIN_CHANNEL_EXTENSIONS) { @@ -274,11 +273,6 @@ export async function syncGatewayConfigBeforeLaunch( for (const [channelType, info] of Object.entries(CHANNEL_PLUGIN_MAP)) { pluginIdToChannel[info.dirName] = channelType; } - // Known manifest IDs that differ from their dirName/channelType - - pluginIdToChannel['openclaw-lark'] = 'feishu'; - pluginIdToChannel['feishu-openclaw-plugin'] = 'feishu'; - for (const pluginId of allowList) { const channelType = pluginIdToChannel[pluginId] ?? pluginId; if (CHANNEL_PLUGIN_MAP[channelType] && !configuredChannels.includes(channelType)) { diff --git a/electron/main/ipc-handlers.ts b/electron/main/ipc-handlers.ts index 2958678..f8ebb3a 100644 --- a/electron/main/ipc-handlers.ts +++ b/electron/main/ipc-handlers.ts @@ -36,7 +36,6 @@ import { toOpenClawChannelType, toUiChannelType } from '../utils/channel-alias'; import { checkUvInstalled, installUv, setupManagedPython } from '../utils/uv-setup'; import { ensureDingTalkPluginInstalled, - ensureFeishuPluginInstalled, ensureWeComPluginInstalled, } from '../utils/plugin-install'; import { updateSkillConfig, getSkillConfig, getAllSkillConfigs } from '../utils/skill-config'; @@ -1497,23 +1496,7 @@ function registerOpenClawHandlers(gatewayManager: GatewayManager): void { 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) { - return { - success: false, - error: installResult.warning || 'Feishu plugin install failed', - }; - } - await saveChannelConfig(channelType, config); - scheduleGatewayChannelSaveRefresh(channelType, `channel:saveConfig (${channelType})`); - return { - success: true, - pluginInstalled: installResult.installed, - warning: installResult.warning, - }; - } + // Feishu is a built-in extension since OpenClaw 2026.4.11 — no plugin install needed await saveChannelConfig(channelType, config); scheduleGatewayChannelSaveRefresh(channelType, `channel:saveConfig (${channelType})`); return { success: true }; diff --git a/electron/utils/channel-config.ts b/electron/utils/channel-config.ts index a461ab3..ff98c69 100644 --- a/electron/utils/channel-config.ts +++ b/electron/utils/channel-config.ts @@ -24,7 +24,7 @@ const CONFIG_FILE = join(OPENCLAW_DIR, 'openclaw.json'); const WECOM_PLUGIN_ID = 'wecom'; // 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 FEISHU_PLUGIN_ID_CANDIDATES = ['feishu', 'openclaw-lark', 'feishu-openclaw-plugin'] as const; const DEFAULT_ACCOUNT_ID = 'default'; // Channels whose plugin schema uses additionalProperties:false, meaning // credential keys MUST NOT appear at the top level of `channels.`. diff --git a/electron/utils/openclaw-auth.ts b/electron/utils/openclaw-auth.ts index 8b322b3..3f24435 100644 --- a/electron/utils/openclaw-auth.ts +++ b/electron/utils/openclaw-auth.ts @@ -208,7 +208,7 @@ async function discoverAgentIds(): Promise { // ── OpenClaw Config Helpers ────────────────────────────────────── const OPENCLAW_CONFIG_PATH = join(homedir(), '.openclaw', 'openclaw.json'); -const FEISHU_PLUGIN_ID_CANDIDATES = ['openclaw-lark', 'feishu-openclaw-plugin'] as const; +const FEISHU_PLUGIN_ID_CANDIDATES = ['feishu', 'openclaw-lark', 'feishu-openclaw-plugin'] as const; const VALID_COMPACTION_MODES = new Set(['default', 'safeguard']); const BUILTIN_CHANNEL_IDS = new Set([ 'discord', diff --git a/electron/utils/plugin-install.ts b/electron/utils/plugin-install.ts index 6c294b0..db08bf3 100644 --- a/electron/utils/plugin-install.ts +++ b/electron/utils/plugin-install.ts @@ -2,7 +2,7 @@ * Shared OpenClaw Plugin Install Utilities * * Provides version-aware install/upgrade logic for bundled OpenClaw plugins - * (DingTalk, WeCom, Feishu, WeChat). Used both at app startup (to auto-upgrade + * (DingTalk, WeCom, 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 @@ -233,7 +233,6 @@ function patchPluginEntryIds(targetDir: string): void { const PLUGIN_NPM_NAMES: Record = { dingtalk: '@soimy/dingtalk', wecom: '@wecom/wecom-openclaw-plugin', - 'feishu-openclaw-plugin': '@larksuite/openclaw-lark', 'openclaw-weixin': '@tencent-weixin/openclaw-weixin', }; @@ -503,15 +502,6 @@ export function ensureWeComPluginInstalled(): { installed: boolean; warning?: st return ensurePluginInstalled('wecom', buildCandidateSources('wecom'), 'WeCom'); } -export function ensureFeishuPluginInstalled(): { installed: boolean; warning?: string } { - return ensurePluginInstalled( - 'feishu-openclaw-plugin', - buildCandidateSources('feishu-openclaw-plugin'), - 'Feishu', - ); -} - - export function ensureWeChatPluginInstalled(): { installed: boolean; warning?: string } { return ensurePluginInstalled('openclaw-weixin', buildCandidateSources('openclaw-weixin'), 'WeChat'); @@ -525,8 +515,6 @@ export function ensureWeChatPluginInstalled(): { installed: boolean; warning?: s const ALL_BUNDLED_PLUGINS = [ { fn: ensureDingTalkPluginInstalled, label: 'DingTalk' }, { fn: ensureWeComPluginInstalled, label: 'WeCom' }, - - { fn: ensureFeishuPluginInstalled, label: 'Feishu' }, { fn: ensureWeChatPluginInstalled, label: 'WeChat' }, ] as const; diff --git a/package.json b/package.json index 4dbc344..7e7224e 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ }, "devDependencies": { "@eslint/js": "^10.0.1", - "@larksuite/openclaw-lark": "2026.4.7", + "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-label": "^2.1.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4f63ab7..4fc3118 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,9 +43,6 @@ importers: '@eslint/js': specifier: ^10.0.1 version: 10.0.1(eslint@10.1.0(jiti@1.21.7)) - '@larksuite/openclaw-lark': - specifier: 2026.4.7 - version: 2026.4.7(openclaw@2026.4.11(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.1)(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(apache-arrow@18.1.0)(encoding@0.1.13)(typescript@5.9.3)) '@playwright/test': specifier: ^1.56.1 version: 1.59.0 @@ -1307,16 +1304,6 @@ packages: peerDependencies: apache-arrow: '>=15.0.0 <=18.1.0' - '@larksuite/openclaw-lark@2026.4.7': - resolution: {integrity: sha512-oiS7hHwJpoOQCHjgAT2xPTO9zmmUKEje2kgsYC+Q8ZMu0gn/sI+FE2NYnQ3dVcgqw7z+2rdajgcTP6kkisFxNw==} - engines: {node: '>=22'} - hasBin: true - peerDependencies: - openclaw: '>=2026.3.22' - peerDependenciesMeta: - openclaw: - optional: true - '@larksuiteoapi/node-sdk@1.60.0': resolution: {integrity: sha512-MS1eXx7K6HHIyIcCBkJLb21okoa8ZatUGQWZaCCUePm6a37RWFmT6ZKlKvHxAanSX26wNuNlwP0RhgscsE+T6g==} @@ -4430,11 +4417,6 @@ packages: image-q@4.0.0: resolution: {integrity: sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==} - image-size@2.0.2: - resolution: {integrity: sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w==} - engines: {node: '>=16.x'} - hasBin: true - immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} @@ -8428,19 +8410,6 @@ snapshots: '@lancedb/lancedb-win32-arm64-msvc': 0.27.2 '@lancedb/lancedb-win32-x64-msvc': 0.27.2 - '@larksuite/openclaw-lark@2026.4.7(openclaw@2026.4.11(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.1)(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(apache-arrow@18.1.0)(encoding@0.1.13)(typescript@5.9.3))': - dependencies: - '@larksuiteoapi/node-sdk': 1.60.0 - '@sinclair/typebox': 0.34.48 - image-size: 2.0.2 - zod: 4.3.6 - optionalDependencies: - openclaw: 2026.4.11(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.1)(@napi-rs/canvas@0.1.97)(@types/express@5.0.6)(apache-arrow@18.1.0)(encoding@0.1.13)(typescript@5.9.3) - transitivePeerDependencies: - - bufferutil - - debug - - utf-8-validate - '@larksuiteoapi/node-sdk@1.60.0': dependencies: axios: 1.13.6(debug@4.4.3) @@ -9921,7 +9890,7 @@ snapshots: '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 25.5.0 + '@types/node': 25.6.0 '@types/bun@1.3.11': dependencies: @@ -9946,7 +9915,7 @@ snapshots: '@types/connect@3.4.38': dependencies: - '@types/node': 25.5.0 + '@types/node': 25.6.0 '@types/debug@4.1.13': dependencies: @@ -9966,7 +9935,7 @@ snapshots: '@types/express-serve-static-core@5.1.1': dependencies: - '@types/node': 25.5.0 + '@types/node': 25.6.0 '@types/qs': 6.15.0 '@types/range-parser': 1.2.7 '@types/send': 1.2.1 @@ -10056,12 +10025,12 @@ snapshots: '@types/send@1.2.1': dependencies: - '@types/node': 25.5.0 + '@types/node': 25.6.0 '@types/serve-static@2.2.0': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 25.5.0 + '@types/node': 25.6.0 '@types/unist@2.0.11': {} @@ -12032,8 +12001,6 @@ snapshots: dependencies: '@types/node': 16.9.1 - image-size@2.0.2: {} - immediate@3.0.6: {} imurmurhash@0.1.4: {} diff --git a/scripts/after-pack.cjs b/scripts/after-pack.cjs index e3184e5..dd038c4 100644 --- a/scripts/after-pack.cjs +++ b/scripts/after-pack.cjs @@ -575,7 +575,6 @@ exports.default = async function afterPack(context) { const BUNDLED_PLUGINS = [ { npmName: '@soimy/dingtalk', pluginId: 'dingtalk' }, { npmName: '@wecom/wecom-openclaw-plugin', pluginId: 'wecom' }, - { npmName: '@larksuite/openclaw-lark', pluginId: 'feishu-openclaw-plugin' }, { npmName: '@tencent-weixin/openclaw-weixin', pluginId: 'openclaw-weixin' }, ]; diff --git a/scripts/bundle-openclaw-plugins.mjs b/scripts/bundle-openclaw-plugins.mjs index 1d34992..4853cfb 100644 --- a/scripts/bundle-openclaw-plugins.mjs +++ b/scripts/bundle-openclaw-plugins.mjs @@ -5,10 +5,13 @@ * * Build a self-contained mirror of OpenClaw third-party plugins for packaging. * Current plugins: - * - @soimy/dingtalk -> build/openclaw-plugins/dingtalk + * - @soimy/dingtalk -> build/openclaw-plugins/dingtalk * - @wecom/wecom-openclaw-plugin -> build/openclaw-plugins/wecom * - @tencent-weixin/openclaw-weixin -> build/openclaw-plugins/openclaw-weixin * + * Note: Feishu (@larksuite/openclaw-lark) is now a built-in extension in + * OpenClaw 2026.4.11+ and no longer needs to be bundled separately. + * * The output plugin directory contains: * - plugin source files (index.ts, openclaw.plugin.json, package.json, ...) * - plugin runtime node_modules/ (flattened direct + transitive deps) @@ -38,7 +41,6 @@ function normWin(p) { const PLUGINS = [ { npmName: '@soimy/dingtalk', pluginId: 'dingtalk' }, { npmName: '@wecom/wecom-openclaw-plugin', pluginId: 'wecom' }, - { npmName: '@larksuite/openclaw-lark', pluginId: 'feishu-openclaw-plugin' }, { npmName: '@tencent-weixin/openclaw-weixin', pluginId: 'openclaw-weixin' }, ]; diff --git a/scripts/bundle-openclaw.mjs b/scripts/bundle-openclaw.mjs index 838a503..307fe5b 100644 --- a/scripts/bundle-openclaw.mjs +++ b/scripts/bundle-openclaw.mjs @@ -470,7 +470,7 @@ function cleanupBundle(outputDir) { 'node_modules/koffi/src', 'node_modules/koffi/vendor', 'node_modules/koffi/doc', - 'extensions/feishu', // Removed in favor of official @larksuite/openclaw-lark plugin + // Note: extensions/feishu is the built-in Feishu plugin since OpenClaw 2026.4.11 ]; for (const rel of LARGE_REMOVALS) { if (rmSafe(path.join(outputDir, rel))) removedCount++; diff --git a/tests/unit/channel-routes.test.ts b/tests/unit/channel-routes.test.ts index c434550..919a2b0 100644 --- a/tests/unit/channel-routes.test.ts +++ b/tests/unit/channel-routes.test.ts @@ -44,7 +44,6 @@ vi.mock('@electron/utils/agent-config', () => ({ vi.mock('@electron/utils/plugin-install', () => ({ ensureDingTalkPluginInstalled: vi.fn(), - ensureFeishuPluginInstalled: vi.fn(), ensureWeChatPluginInstalled: vi.fn(), ensureWeComPluginInstalled: vi.fn(), }));