Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 38 additions & 38 deletions electron/gateway/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { GatewayManager, GatewayStatus } from './manager';
/**
* Channel types supported by OpenClaw
*/
export type ChannelType = 'whatsapp' | 'telegram' | 'discord' | 'slack' | 'wechat';
export type ChannelType = 'whatsapp' | 'telegram' | 'discord' | 'wechat';

/**
* Channel status
Expand Down Expand Up @@ -107,223 +107,223 @@ export interface ProviderConfig {
* Typed wrapper around GatewayManager for making RPC calls
*/
export class GatewayClient {
constructor(private manager: GatewayManager) {}
constructor(private manager: GatewayManager) { }

/**
* Get current gateway status
*/
getStatus(): GatewayStatus {
return this.manager.getStatus();
}

/**
* Check if gateway is connected
*/
isConnected(): boolean {
return this.manager.isConnected();
}

// ==================== Channel Methods ====================

/**
* List all channels
*/
async listChannels(): Promise<Channel[]> {
return this.manager.rpc<Channel[]>('channels.list');
}

/**
* Get channel by ID
*/
async getChannel(channelId: string): Promise<Channel> {
return this.manager.rpc<Channel>('channels.get', { channelId });
}

/**
* Connect a channel
*/
async connectChannel(channelId: string): Promise<void> {
return this.manager.rpc<void>('channels.connect', { channelId });
}

/**
* Disconnect a channel
*/
async disconnectChannel(channelId: string): Promise<void> {
return this.manager.rpc<void>('channels.disconnect', { channelId });
}

/**
* Get QR code for channel connection (e.g., WhatsApp)
*/
async getChannelQRCode(channelType: ChannelType): Promise<string> {
return this.manager.rpc<string>('channels.getQRCode', { channelType });
}

// ==================== Skill Methods ====================

/**
* List all skills
*/
async listSkills(): Promise<Skill[]> {
return this.manager.rpc<Skill[]>('skills.list');
}

/**
* Enable a skill
*/
async enableSkill(skillId: string): Promise<void> {
return this.manager.rpc<void>('skills.enable', { skillId });
}

/**
* Disable a skill
*/
async disableSkill(skillId: string): Promise<void> {
return this.manager.rpc<void>('skills.disable', { skillId });
}

/**
* Get skill configuration
*/
async getSkillConfig(skillId: string): Promise<Record<string, unknown>> {
return this.manager.rpc<Record<string, unknown>>('skills.getConfig', { skillId });
}

/**
* Update skill configuration
*/
async updateSkillConfig(skillId: string, config: Record<string, unknown>): Promise<void> {
return this.manager.rpc<void>('skills.updateConfig', { skillId, config });
}

// ==================== Chat Methods ====================

/**
* Send a chat message
*/
async sendMessage(content: string, channelId?: string): Promise<ChatMessage> {
return this.manager.rpc<ChatMessage>('chat.send', { content, channelId });
}

/**
* Get chat history
*/
async getChatHistory(limit = 50, offset = 0): Promise<ChatMessage[]> {
return this.manager.rpc<ChatMessage[]>('chat.history', { limit, offset });
}

/**
* Clear chat history
*/
async clearChatHistory(): Promise<void> {
return this.manager.rpc<void>('chat.clear');
}

// ==================== Cron Methods ====================

/**
* List all cron tasks
*/
async listCronTasks(): Promise<CronTask[]> {
return this.manager.rpc<CronTask[]>('cron.list');
}

/**
* Create a new cron task
*/
async createCronTask(task: Omit<CronTask, 'id' | 'status'>): Promise<CronTask> {
return this.manager.rpc<CronTask>('cron.create', task);
}

/**
* Update a cron task
*/
async updateCronTask(taskId: string, updates: Partial<CronTask>): Promise<CronTask> {
return this.manager.rpc<CronTask>('cron.update', { taskId, ...updates });
}

/**
* Delete a cron task
*/
async deleteCronTask(taskId: string): Promise<void> {
return this.manager.rpc<void>('cron.delete', { taskId });
}

/**
* Run a cron task immediately
*/
async runCronTask(taskId: string): Promise<void> {
return this.manager.rpc<void>('cron.run', { taskId });
}

// ==================== Provider Methods ====================

/**
* List configured AI providers
*/
async listProviders(): Promise<ProviderConfig[]> {
return this.manager.rpc<ProviderConfig[]>('providers.list');
}

/**
* Add or update a provider
*/
async setProvider(provider: ProviderConfig): Promise<void> {
return this.manager.rpc<void>('providers.set', provider);
}

/**
* Remove a provider
*/
async removeProvider(providerId: string): Promise<void> {
return this.manager.rpc<void>('providers.remove', { providerId });
}

/**
* Test provider connection
*/
async testProvider(providerId: string): Promise<{ success: boolean; error?: string }> {
return this.manager.rpc<{ success: boolean; error?: string }>('providers.test', { providerId });
}

// ==================== System Methods ====================

/**
* Get Gateway health status
*/
async getHealth(): Promise<{ status: string; uptime: number; version?: string }> {
return this.manager.rpc<{ status: string; uptime: number; version?: string }>('system.health');
}

/**
* Get Gateway configuration
*/
async getConfig(): Promise<Record<string, unknown>> {
return this.manager.rpc<Record<string, unknown>>('system.config');
}

/**
* Update Gateway configuration
*/
async updateConfig(config: Record<string, unknown>): Promise<void> {
return this.manager.rpc<void>('system.updateConfig', config);
}

/**
* Get Gateway version info
*/
async getVersion(): Promise<{ version: string; nodeVersion?: string; platform?: string }> {
return this.manager.rpc<{ version: string; nodeVersion?: string; platform?: string }>('system.version');
}

/**
* Get available skill bundles
*/
async getSkillBundles(): Promise<SkillBundle[]> {
return this.manager.rpc<SkillBundle[]>('skills.bundles');
}

/**
* Install a skill bundle
*/
Expand Down
51 changes: 51 additions & 0 deletions electron/main/ipc-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
} from '../utils/channel-config';
import { checkUvInstalled, installUv, setupManagedPython } from '../utils/uv-setup';
import { updateSkillConfig, getSkillConfig, getAllSkillConfigs } from '../utils/skill-config';
import { whatsAppLoginManager } from '../utils/whatsapp-login';

/**
* Register all IPC handlers
Expand Down Expand Up @@ -80,6 +81,9 @@ export function registerIpcHandlers(

// Window control handlers (for custom title bar on Windows/Linux)
registerWindowHandlers(mainWindow);

// WhatsApp handlers
registerWhatsAppHandlers(mainWindow);
}

/**
Expand Down Expand Up @@ -591,6 +595,53 @@ function registerOpenClawHandlers(): void {
});
}

/**
* WhatsApp Login Handlers
*/
function registerWhatsAppHandlers(mainWindow: BrowserWindow): void {
// Request WhatsApp QR code
ipcMain.handle('channel:requestWhatsAppQr', async (_, accountId: string) => {
try {
await whatsAppLoginManager.start(accountId);
return { success: true };
} catch (error) {
return { success: false, error: String(error) };
}
});

// Cancel WhatsApp login
ipcMain.handle('channel:cancelWhatsAppQr', async () => {
try {
await whatsAppLoginManager.stop();
return { success: true };
} catch (error) {
return { success: false, error: String(error) };
}
});

// Check WhatsApp status (is it active?)
// ipcMain.handle('channel:checkWhatsAppStatus', ...)

// Forward events to renderer
whatsAppLoginManager.on('qr', (data) => {
if (!mainWindow.isDestroyed()) {
mainWindow.webContents.send('channel:whatsapp-qr', data);
}
});

whatsAppLoginManager.on('success', (data) => {
if (!mainWindow.isDestroyed()) {
mainWindow.webContents.send('channel:whatsapp-success', data);
}
});

whatsAppLoginManager.on('error', (error) => {
if (!mainWindow.isDestroyed()) {
mainWindow.webContents.send('channel:whatsapp-error', error);
}
});
}


/**
* Provider-related IPC handlers
Expand Down
7 changes: 7 additions & 0 deletions electron/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@ const electronAPI = {
'channel:listConfigured',
'channel:setEnabled',
'channel:validate',
'channel:validate',
'channel:validateCredentials',
// WhatsApp
'channel:requestWhatsAppQr',
'channel:cancelWhatsAppQr',
// ClawHub
'clawhub:search',
'clawhub:install',
Expand Down Expand Up @@ -132,6 +136,9 @@ const electronAPI = {
'gateway:notification',
'gateway:channel-status',
'gateway:chat-message',
'channel:whatsapp-qr',
'channel:whatsapp-success',
'channel:whatsapp-error',
'gateway:exit',
'gateway:error',
'navigate',
Expand Down
Loading