feat(channels): add DingTalk via bundled plugin mirror and pure Node deploy (#215)
This commit is contained in:
committed by
GitHub
Unverified
parent
d4f77a442c
commit
d63810f54b
@@ -7,7 +7,7 @@ import { GatewayManager, GatewayStatus } from './manager';
|
||||
/**
|
||||
* Channel types supported by OpenClaw
|
||||
*/
|
||||
export type ChannelType = 'whatsapp' | 'telegram' | 'discord' | 'wechat';
|
||||
export type ChannelType = 'whatsapp' | 'dingtalk' | 'telegram' | 'discord' | 'wechat';
|
||||
|
||||
/**
|
||||
* Channel status
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Registers all IPC handlers for main-renderer communication
|
||||
*/
|
||||
import { ipcMain, BrowserWindow, shell, dialog, app, nativeImage } from 'electron';
|
||||
import { existsSync } from 'node:fs';
|
||||
import { existsSync, cpSync, mkdirSync, rmSync } from 'node:fs';
|
||||
import { homedir } from 'node:os';
|
||||
import { join, extname, basename } from 'node:path';
|
||||
import crypto from 'node:crypto';
|
||||
@@ -608,6 +608,50 @@ function registerGatewayHandlers(
|
||||
* For checking package status and channel configuration
|
||||
*/
|
||||
function registerOpenClawHandlers(gatewayManager: GatewayManager): void {
|
||||
async function ensureDingTalkPluginInstalled(): Promise<{ installed: boolean; warning?: string }> {
|
||||
const targetDir = join(homedir(), '.openclaw', 'extensions', 'dingtalk');
|
||||
const targetManifest = join(targetDir, 'openclaw.plugin.json');
|
||||
|
||||
if (existsSync(targetManifest)) {
|
||||
logger.info('DingTalk plugin already installed from local mirror');
|
||||
return { installed: true };
|
||||
}
|
||||
|
||||
const candidateSources = app.isPackaged
|
||||
? [join(process.resourcesPath, 'openclaw-plugins', 'dingtalk')]
|
||||
: [
|
||||
join(app.getAppPath(), 'build', 'openclaw-plugins', 'dingtalk'),
|
||||
join(process.cwd(), 'build', 'openclaw-plugins', 'dingtalk'),
|
||||
join(__dirname, '../../build/openclaw-plugins/dingtalk'),
|
||||
];
|
||||
|
||||
const sourceDir = candidateSources.find((dir) => existsSync(join(dir, 'openclaw.plugin.json')));
|
||||
if (!sourceDir) {
|
||||
return {
|
||||
installed: false,
|
||||
warning: 'Bundled DingTalk plugin mirror not found. Run: pnpm run bundle:openclaw-plugins',
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
mkdirSync(join(homedir(), '.openclaw', 'extensions'), { recursive: true });
|
||||
rmSync(targetDir, { recursive: true, force: true });
|
||||
cpSync(sourceDir, targetDir, { recursive: true, dereference: true });
|
||||
|
||||
if (!existsSync(targetManifest)) {
|
||||
return { installed: false, warning: 'Failed to install DingTalk plugin mirror (manifest missing).' };
|
||||
}
|
||||
|
||||
logger.info(`Installed DingTalk plugin from bundled mirror: ${sourceDir}`);
|
||||
return { installed: true };
|
||||
} catch (error) {
|
||||
logger.warn('Failed to install DingTalk plugin from bundled mirror:', error);
|
||||
return {
|
||||
installed: false,
|
||||
warning: 'Failed to install bundled DingTalk plugin mirror',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Get OpenClaw package status
|
||||
ipcMain.handle('openclaw:status', () => {
|
||||
@@ -666,12 +710,23 @@ function registerOpenClawHandlers(gatewayManager: GatewayManager): void {
|
||||
ipcMain.handle('channel:saveConfig', async (_, channelType: string, config: Record<string, unknown>) => {
|
||||
try {
|
||||
logger.info('channel:saveConfig', { channelType, keys: Object.keys(config || {}) });
|
||||
if (channelType === 'dingtalk') {
|
||||
const installResult = await ensureDingTalkPluginInstalled();
|
||||
if (!installResult.installed) {
|
||||
return {
|
||||
success: false,
|
||||
error: installResult.warning || 'DingTalk plugin install failed',
|
||||
};
|
||||
}
|
||||
saveChannelConfig(channelType, config);
|
||||
return {
|
||||
success: true,
|
||||
pluginInstalled: installResult.installed,
|
||||
warning: installResult.warning,
|
||||
};
|
||||
}
|
||||
await saveChannelConfig(channelType, config);
|
||||
// Debounced restart so the gateway picks up the new channel config.
|
||||
// The gateway watches openclaw.json, but a restart ensures a clean
|
||||
// start for newly-added channels. Using debouncedRestart() here
|
||||
// instead of an explicit restart on the frontend side means that
|
||||
// rapid config changes (e.g. setup wizard) coalesce into one restart.
|
||||
gatewayManager.debouncedRestart();
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
|
||||
@@ -86,6 +86,36 @@ export async function saveChannelConfig(
|
||||
): Promise<void> {
|
||||
const currentConfig = await readOpenClawConfig();
|
||||
|
||||
// DingTalk is a channel plugin; make sure it's explicitly allowed.
|
||||
// Newer OpenClaw versions may not load non-bundled plugins when allowlist is empty.
|
||||
if (channelType === 'dingtalk') {
|
||||
if (!currentConfig.plugins) {
|
||||
currentConfig.plugins = {};
|
||||
}
|
||||
currentConfig.plugins.enabled = true;
|
||||
const allow = Array.isArray(currentConfig.plugins.allow)
|
||||
? currentConfig.plugins.allow as string[]
|
||||
: [];
|
||||
if (!allow.includes('dingtalk')) {
|
||||
currentConfig.plugins.allow = [...allow, 'dingtalk'];
|
||||
}
|
||||
}
|
||||
|
||||
// DingTalk is a channel plugin; make sure it's explicitly allowed.
|
||||
// Newer OpenClaw versions may not load non-bundled plugins when allowlist is empty.
|
||||
if (channelType === 'dingtalk') {
|
||||
if (!currentConfig.plugins) {
|
||||
currentConfig.plugins = {};
|
||||
}
|
||||
currentConfig.plugins.enabled = true;
|
||||
const allow = Array.isArray(currentConfig.plugins.allow)
|
||||
? currentConfig.plugins.allow as string[]
|
||||
: [];
|
||||
if (!allow.includes('dingtalk')) {
|
||||
currentConfig.plugins.allow = [...allow, 'dingtalk'];
|
||||
}
|
||||
}
|
||||
|
||||
// Plugin-based channels (e.g. WhatsApp) go under plugins.entries, not channels
|
||||
if (PLUGIN_CHANNELS.includes(channelType)) {
|
||||
if (!currentConfig.plugins) {
|
||||
|
||||
Reference in New Issue
Block a user