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.

This commit is contained in:
Haze
2026-04-13 17:39:48 +08:00
parent cf43237c67
commit 5b8a35391d
12 changed files with 17 additions and 93 deletions

View File

@@ -25,7 +25,6 @@ import {
} from '../../utils/agent-config'; } from '../../utils/agent-config';
import { import {
ensureDingTalkPluginInstalled, ensureDingTalkPluginInstalled,
ensureFeishuPluginInstalled,
ensureWeChatPluginInstalled, ensureWeChatPluginInstalled,
ensureWeComPluginInstalled, ensureWeComPluginInstalled,
} from '../../utils/plugin-install'; } from '../../utils/plugin-install';
@@ -1349,14 +1348,7 @@ export async function handleChannelRoutes(
return true; return true;
} }
} }
// QQBot is a built-in channel since OpenClaw 3.31 — no plugin install needed // Feishu is a built-in extension since OpenClaw 2026.4.11 — 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;
}
}
if (storedChannelType === OPENCLAW_WECHAT_CHANNEL_TYPE) { if (storedChannelType === OPENCLAW_WECHAT_CHANNEL_TYPE) {
const installResult = await ensureWeChatPluginInstalled(); const installResult = await ensureWeChatPluginInstalled();
if (!installResult.installed) { if (!installResult.installed) {

View File

@@ -48,7 +48,6 @@ export interface GatewayLaunchContext {
const CHANNEL_PLUGIN_MAP: Record<string, { dirName: string; npmName: string }> = { const CHANNEL_PLUGIN_MAP: Record<string, { dirName: string; npmName: string }> = {
dingtalk: { dirName: 'dingtalk', npmName: '@soimy/dingtalk' }, dingtalk: { dirName: 'dingtalk', npmName: '@soimy/dingtalk' },
wecom: { dirName: 'wecom', npmName: '@wecom/wecom-openclaw-plugin' }, 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' }, 'openclaw-weixin': { dirName: 'openclaw-weixin', npmName: '@tencent-weixin/openclaw-weixin' },
}; };
@@ -59,7 +58,7 @@ const CHANNEL_PLUGIN_MAP: Record<string, { dirName: string; npmName: string }> =
* ~/.openclaw/extensions/, the broken copy overrides the working built-in * ~/.openclaw/extensions/, the broken copy overrides the working built-in
* plugin and must be removed. * 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 { function cleanupStaleBuiltInExtensions(): void {
for (const ext of BUILTIN_CHANNEL_EXTENSIONS) { 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)) { for (const [channelType, info] of Object.entries(CHANNEL_PLUGIN_MAP)) {
pluginIdToChannel[info.dirName] = channelType; 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) { for (const pluginId of allowList) {
const channelType = pluginIdToChannel[pluginId] ?? pluginId; const channelType = pluginIdToChannel[pluginId] ?? pluginId;
if (CHANNEL_PLUGIN_MAP[channelType] && !configuredChannels.includes(channelType)) { if (CHANNEL_PLUGIN_MAP[channelType] && !configuredChannels.includes(channelType)) {

View File

@@ -36,7 +36,6 @@ import { toOpenClawChannelType, toUiChannelType } from '../utils/channel-alias';
import { checkUvInstalled, installUv, setupManagedPython } from '../utils/uv-setup'; import { checkUvInstalled, installUv, setupManagedPython } from '../utils/uv-setup';
import { import {
ensureDingTalkPluginInstalled, ensureDingTalkPluginInstalled,
ensureFeishuPluginInstalled,
ensureWeComPluginInstalled, ensureWeComPluginInstalled,
} from '../utils/plugin-install'; } from '../utils/plugin-install';
import { updateSkillConfig, getSkillConfig, getAllSkillConfigs } from '../utils/skill-config'; import { updateSkillConfig, getSkillConfig, getAllSkillConfigs } from '../utils/skill-config';
@@ -1497,23 +1496,7 @@ function registerOpenClawHandlers(gatewayManager: GatewayManager): void {
warning: installResult.warning, warning: installResult.warning,
}; };
} }
// QQBot is a built-in channel since OpenClaw 3.31 — no plugin install needed // Feishu is a built-in extension since OpenClaw 2026.4.11 — 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,
};
}
await saveChannelConfig(channelType, config); await saveChannelConfig(channelType, config);
scheduleGatewayChannelSaveRefresh(channelType, `channel:saveConfig (${channelType})`); scheduleGatewayChannelSaveRefresh(channelType, `channel:saveConfig (${channelType})`);
return { success: true }; return { success: true };

View File

@@ -24,7 +24,7 @@ const CONFIG_FILE = join(OPENCLAW_DIR, 'openclaw.json');
const WECOM_PLUGIN_ID = 'wecom'; const WECOM_PLUGIN_ID = 'wecom';
// Note: QQBot is a built-in channel since OpenClaw 3.31 — no plugin ID needed. // Note: QQBot is a built-in channel since OpenClaw 3.31 — no plugin ID needed.
const WECHAT_PLUGIN_ID = OPENCLAW_WECHAT_CHANNEL_TYPE; 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'; const DEFAULT_ACCOUNT_ID = 'default';
// Channels whose plugin schema uses additionalProperties:false, meaning // Channels whose plugin schema uses additionalProperties:false, meaning
// credential keys MUST NOT appear at the top level of `channels.<type>`. // credential keys MUST NOT appear at the top level of `channels.<type>`.

View File

@@ -208,7 +208,7 @@ async function discoverAgentIds(): Promise<string[]> {
// ── OpenClaw Config Helpers ────────────────────────────────────── // ── OpenClaw Config Helpers ──────────────────────────────────────
const OPENCLAW_CONFIG_PATH = join(homedir(), '.openclaw', 'openclaw.json'); 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 VALID_COMPACTION_MODES = new Set(['default', 'safeguard']);
const BUILTIN_CHANNEL_IDS = new Set([ const BUILTIN_CHANNEL_IDS = new Set([
'discord', 'discord',

View File

@@ -2,7 +2,7 @@
* Shared OpenClaw Plugin Install Utilities * Shared OpenClaw Plugin Install Utilities
* *
* Provides version-aware install/upgrade logic for bundled OpenClaw plugins * 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. * 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 * 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<string, string> = { const PLUGIN_NPM_NAMES: Record<string, string> = {
dingtalk: '@soimy/dingtalk', dingtalk: '@soimy/dingtalk',
wecom: '@wecom/wecom-openclaw-plugin', wecom: '@wecom/wecom-openclaw-plugin',
'feishu-openclaw-plugin': '@larksuite/openclaw-lark',
'openclaw-weixin': '@tencent-weixin/openclaw-weixin', 'openclaw-weixin': '@tencent-weixin/openclaw-weixin',
}; };
@@ -503,15 +502,6 @@ export function ensureWeComPluginInstalled(): { installed: boolean; warning?: st
return ensurePluginInstalled('wecom', buildCandidateSources('wecom'), 'WeCom'); 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 } { export function ensureWeChatPluginInstalled(): { installed: boolean; warning?: string } {
return ensurePluginInstalled('openclaw-weixin', buildCandidateSources('openclaw-weixin'), 'WeChat'); return ensurePluginInstalled('openclaw-weixin', buildCandidateSources('openclaw-weixin'), 'WeChat');
@@ -525,8 +515,6 @@ export function ensureWeChatPluginInstalled(): { installed: boolean; warning?: s
const ALL_BUNDLED_PLUGINS = [ const ALL_BUNDLED_PLUGINS = [
{ fn: ensureDingTalkPluginInstalled, label: 'DingTalk' }, { fn: ensureDingTalkPluginInstalled, label: 'DingTalk' },
{ fn: ensureWeComPluginInstalled, label: 'WeCom' }, { fn: ensureWeComPluginInstalled, label: 'WeCom' },
{ fn: ensureFeishuPluginInstalled, label: 'Feishu' },
{ fn: ensureWeChatPluginInstalled, label: 'WeChat' }, { fn: ensureWeChatPluginInstalled, label: 'WeChat' },
] as const; ] as const;

View File

@@ -79,7 +79,7 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^10.0.1", "@eslint/js": "^10.0.1",
"@larksuite/openclaw-lark": "2026.4.7",
"@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.8", "@radix-ui/react-label": "^2.1.8",

43
pnpm-lock.yaml generated
View File

@@ -43,9 +43,6 @@ importers:
'@eslint/js': '@eslint/js':
specifier: ^10.0.1 specifier: ^10.0.1
version: 10.0.1(eslint@10.1.0(jiti@1.21.7)) 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': '@playwright/test':
specifier: ^1.56.1 specifier: ^1.56.1
version: 1.59.0 version: 1.59.0
@@ -1307,16 +1304,6 @@ packages:
peerDependencies: peerDependencies:
apache-arrow: '>=15.0.0 <=18.1.0' 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': '@larksuiteoapi/node-sdk@1.60.0':
resolution: {integrity: sha512-MS1eXx7K6HHIyIcCBkJLb21okoa8ZatUGQWZaCCUePm6a37RWFmT6ZKlKvHxAanSX26wNuNlwP0RhgscsE+T6g==} resolution: {integrity: sha512-MS1eXx7K6HHIyIcCBkJLb21okoa8ZatUGQWZaCCUePm6a37RWFmT6ZKlKvHxAanSX26wNuNlwP0RhgscsE+T6g==}
@@ -4430,11 +4417,6 @@ packages:
image-q@4.0.0: image-q@4.0.0:
resolution: {integrity: sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==} 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: immediate@3.0.6:
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
@@ -8428,19 +8410,6 @@ snapshots:
'@lancedb/lancedb-win32-arm64-msvc': 0.27.2 '@lancedb/lancedb-win32-arm64-msvc': 0.27.2
'@lancedb/lancedb-win32-x64-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': '@larksuiteoapi/node-sdk@1.60.0':
dependencies: dependencies:
axios: 1.13.6(debug@4.4.3) axios: 1.13.6(debug@4.4.3)
@@ -9921,7 +9890,7 @@ snapshots:
'@types/body-parser@1.19.6': '@types/body-parser@1.19.6':
dependencies: dependencies:
'@types/connect': 3.4.38 '@types/connect': 3.4.38
'@types/node': 25.5.0 '@types/node': 25.6.0
'@types/bun@1.3.11': '@types/bun@1.3.11':
dependencies: dependencies:
@@ -9946,7 +9915,7 @@ snapshots:
'@types/connect@3.4.38': '@types/connect@3.4.38':
dependencies: dependencies:
'@types/node': 25.5.0 '@types/node': 25.6.0
'@types/debug@4.1.13': '@types/debug@4.1.13':
dependencies: dependencies:
@@ -9966,7 +9935,7 @@ snapshots:
'@types/express-serve-static-core@5.1.1': '@types/express-serve-static-core@5.1.1':
dependencies: dependencies:
'@types/node': 25.5.0 '@types/node': 25.6.0
'@types/qs': 6.15.0 '@types/qs': 6.15.0
'@types/range-parser': 1.2.7 '@types/range-parser': 1.2.7
'@types/send': 1.2.1 '@types/send': 1.2.1
@@ -10056,12 +10025,12 @@ snapshots:
'@types/send@1.2.1': '@types/send@1.2.1':
dependencies: dependencies:
'@types/node': 25.5.0 '@types/node': 25.6.0
'@types/serve-static@2.2.0': '@types/serve-static@2.2.0':
dependencies: dependencies:
'@types/http-errors': 2.0.5 '@types/http-errors': 2.0.5
'@types/node': 25.5.0 '@types/node': 25.6.0
'@types/unist@2.0.11': {} '@types/unist@2.0.11': {}
@@ -12032,8 +12001,6 @@ snapshots:
dependencies: dependencies:
'@types/node': 16.9.1 '@types/node': 16.9.1
image-size@2.0.2: {}
immediate@3.0.6: {} immediate@3.0.6: {}
imurmurhash@0.1.4: {} imurmurhash@0.1.4: {}

View File

@@ -575,7 +575,6 @@ exports.default = async function afterPack(context) {
const BUNDLED_PLUGINS = [ const BUNDLED_PLUGINS = [
{ npmName: '@soimy/dingtalk', pluginId: 'dingtalk' }, { npmName: '@soimy/dingtalk', pluginId: 'dingtalk' },
{ npmName: '@wecom/wecom-openclaw-plugin', pluginId: 'wecom' }, { npmName: '@wecom/wecom-openclaw-plugin', pluginId: 'wecom' },
{ npmName: '@larksuite/openclaw-lark', pluginId: 'feishu-openclaw-plugin' },
{ npmName: '@tencent-weixin/openclaw-weixin', pluginId: 'openclaw-weixin' }, { npmName: '@tencent-weixin/openclaw-weixin', pluginId: 'openclaw-weixin' },
]; ];

View File

@@ -5,10 +5,13 @@
* *
* Build a self-contained mirror of OpenClaw third-party plugins for packaging. * Build a self-contained mirror of OpenClaw third-party plugins for packaging.
* Current plugins: * Current plugins:
* - @soimy/dingtalk -> build/openclaw-plugins/dingtalk * - @soimy/dingtalk -> build/openclaw-plugins/dingtalk
* - @wecom/wecom-openclaw-plugin -> build/openclaw-plugins/wecom * - @wecom/wecom-openclaw-plugin -> build/openclaw-plugins/wecom
* - @tencent-weixin/openclaw-weixin -> build/openclaw-plugins/openclaw-weixin * - @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: * The output plugin directory contains:
* - plugin source files (index.ts, openclaw.plugin.json, package.json, ...) * - plugin source files (index.ts, openclaw.plugin.json, package.json, ...)
* - plugin runtime node_modules/ (flattened direct + transitive deps) * - plugin runtime node_modules/ (flattened direct + transitive deps)
@@ -38,7 +41,6 @@ function normWin(p) {
const PLUGINS = [ const PLUGINS = [
{ npmName: '@soimy/dingtalk', pluginId: 'dingtalk' }, { npmName: '@soimy/dingtalk', pluginId: 'dingtalk' },
{ npmName: '@wecom/wecom-openclaw-plugin', pluginId: 'wecom' }, { npmName: '@wecom/wecom-openclaw-plugin', pluginId: 'wecom' },
{ npmName: '@larksuite/openclaw-lark', pluginId: 'feishu-openclaw-plugin' },
{ npmName: '@tencent-weixin/openclaw-weixin', pluginId: 'openclaw-weixin' }, { npmName: '@tencent-weixin/openclaw-weixin', pluginId: 'openclaw-weixin' },
]; ];

View File

@@ -470,7 +470,7 @@ function cleanupBundle(outputDir) {
'node_modules/koffi/src', 'node_modules/koffi/src',
'node_modules/koffi/vendor', 'node_modules/koffi/vendor',
'node_modules/koffi/doc', '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) { for (const rel of LARGE_REMOVALS) {
if (rmSafe(path.join(outputDir, rel))) removedCount++; if (rmSafe(path.join(outputDir, rel))) removedCount++;

View File

@@ -44,7 +44,6 @@ vi.mock('@electron/utils/agent-config', () => ({
vi.mock('@electron/utils/plugin-install', () => ({ vi.mock('@electron/utils/plugin-install', () => ({
ensureDingTalkPluginInstalled: vi.fn(), ensureDingTalkPluginInstalled: vi.fn(),
ensureFeishuPluginInstalled: vi.fn(),
ensureWeChatPluginInstalled: vi.fn(), ensureWeChatPluginInstalled: vi.fn(),
ensureWeComPluginInstalled: vi.fn(), ensureWeComPluginInstalled: vi.fn(),
})); }));