From d14016aaec341fa7e3e322c164b5e27b8f268365 Mon Sep 17 00:00:00 2001 From: dolookl <346676303@qq.com> Date: Wed, 1 Jul 2026 12:13:25 +0800 Subject: [PATCH] fix(feishu): add WebSocket pingTimeout and lifecycle event logging The Feishu adapter's WSClient was created without a pingTimeout, causing the Lark SDK to never detect half-open WebSocket connections. This led to bots becoming unresponsive after idle periods (several hours) without any error logs. The Lark SDK's pingTimeout defaults to 0 (disabled), meaning the pong watchdog is never armed. When a WebSocket connection silently drops (e.g., due to NAT timeout, firewall, or WSL network sleep), the SDK never detects it and never triggers reconnection. Changes: - Add pingTimeout config option (default: 30s) to enable dead connection detection - Add WSClient lifecycle event callbacks for visibility into connection state - Fix stop() to properly close WebSocket before releasing references - Expose pingTimeout as configurable via golem.yaml Fixes #28 --- src/channels/feishu.ts | 12 ++++++++++-- src/workspace.ts | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/channels/feishu.ts b/src/channels/feishu.ts index 11f9ea6..de517b7 100644 --- a/src/channels/feishu.ts +++ b/src/channels/feishu.ts @@ -377,6 +377,11 @@ export class FeishuAdapter implements ChannelAdapter { this.wsClient = new lark.WSClient({ ...baseConfig, loggerLevel: lark.LoggerLevel.info, + pingTimeout: this.config.pingTimeout ?? 30, + onReady: () => console.log('[feishu] WS ready'), + onReconnecting: () => console.log('[feishu] WS reconnecting...'), + onReconnected: () => console.log('[feishu] WS reconnected'), + onError: (err: unknown) => console.error('[feishu] WS error:', (err as Error)?.message), }); await this.wsClient.start({ eventDispatcher }); @@ -635,8 +640,11 @@ export class FeishuAdapter implements ChannelAdapter { } async stop(): Promise { - // WSClient doesn't expose a clean close method in current SDK version; - // setting to null allows GC to collect. + if (this.wsClient) { + try { + this.wsClient.close(); + } catch {} + } this.wsClient = null; this.client = null; } diff --git a/src/workspace.ts b/src/workspace.ts index ee96b1e..94c9d99 100644 --- a/src/workspace.ts +++ b/src/workspace.ts @@ -14,6 +14,8 @@ export interface FeishuChannelConfig { appSecret: string; /** Open platform domain. Use `lark` for Lark global tenants. Default: `feishu`. */ domain?: string; + /** WebSocket pong timeout in seconds. If no pong received within this time, the connection is considered dead and reconnect is triggered. Default: 30. */ + pingTimeout?: number; } export interface DingtalkChannelConfig {