diff --git a/package.json b/package.json index a5a5145c94..970dc51b16 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,6 @@ "dependencies": { "@anthropic-ai/claude-agent-sdk": "0.2.12", "@electron/remote": "^2.0.12", - "@grammyjs/runner": "^2.0.0", "@headlessui/react": "^1.7.18", "@heroicons/react": "^2.1.1", "@larksuiteoapi/node-sdk": "^1.58.0", @@ -100,7 +99,6 @@ "electron-log": "^5.4.3", "extract-zip": "^2.0.1", "form-data": "^4.0.5", - "grammy": "^1.21.0", "js-yaml": "^4.1.1", "katex": "^0.16.21", "mermaid": "^10.9.5", diff --git a/src/main/im/http.ts b/src/main/im/http.ts index 4f791f6447..57edfb454d 100644 --- a/src/main/im/http.ts +++ b/src/main/im/http.ts @@ -1,8 +1,5 @@ import { app, session } from 'electron'; -// Fallback for cases where Electron session is not ready yet. -const nodeFetch = require('node-fetch'); - function linkAbortSignal(source: AbortSignal, controller: AbortController): void { if (source.aborted) { controller.abort(); @@ -17,11 +14,11 @@ export async function fetchWithSystemProxy(url: string, options: RequestInit = { return await session.defaultSession.fetch(url, options); } catch (error) { const message = error instanceof Error ? error.message : String(error); - console.warn(`[IM HTTP] session fetch failed, fallback to node-fetch: ${message}`); + console.warn(`[IM HTTP] session fetch failed, fallback to global fetch: ${message}`); } } - return nodeFetch(url, options); + return fetch(url, options); } export async function fetchJsonWithTimeout( diff --git a/src/main/im/imGatewayManager.ts b/src/main/im/imGatewayManager.ts index 28044f6cd8..96c20b6d4f 100644 --- a/src/main/im/imGatewayManager.ts +++ b/src/main/im/imGatewayManager.ts @@ -622,7 +622,6 @@ export class IMGatewayManager extends EventEmitter { feishu: this.feishuGateway.getStatus(), telegram: telegramStatus, qq: this.qqGateway.getStatus(), - telegram: this.telegramGateway.getStatus(), discord: this.discordGateway.getStatus(), nim: this.nimGateway.getStatus(), xiaomifeng: this.xiaomifengGateway.getStatus(), @@ -992,7 +991,7 @@ export class IMGatewayManager extends EventEmitter { * Check if any gateway is connected */ isAnyConnected(): boolean { - return this.dingtalkGateway.isConnected() || this.feishuGateway.isConnected() || this.telegramGateway.isConnected() || this.discordGateway.isConnected() || this.nimGateway.isConnected() || this.xiaomifengGateway.isConnected() || this.qqGateway.isConnected() || this.wecomGateway.isConnected(); + return this.dingtalkGateway.isConnected() || this.feishuGateway.isConnected() || this.discordGateway.isConnected() || this.nimGateway.isConnected() || this.xiaomifengGateway.isConnected() || this.qqGateway.isConnected() || this.wecomGateway.isConnected(); } /** diff --git a/src/main/im/imStore.ts b/src/main/im/imStore.ts index 52e67a2202..1124a05a40 100644 --- a/src/main/im/imStore.ts +++ b/src/main/im/imStore.ts @@ -10,7 +10,6 @@ import { FeishuConfig, TelegramOpenClawConfig, QQConfig, - TelegramConfig, DiscordConfig, NimConfig, XiaomifengConfig, @@ -22,7 +21,6 @@ import { DEFAULT_FEISHU_CONFIG, DEFAULT_TELEGRAM_OPENCLAW_CONFIG, DEFAULT_QQ_CONFIG, - DEFAULT_TELEGRAM_CONFIG, DEFAULT_DISCORD_CONFIG, DEFAULT_NIM_CONFIG, DEFAULT_XIAOMIFENG_CONFIG, @@ -334,6 +332,8 @@ export class IMStore { setTelegramOpenClawConfig(config: Partial): void { const current = this.getTelegramOpenClawConfig(); this.setConfigValue('telegramOpenClaw', { ...current, ...config }); + } + // ==================== QQ Config ==================== getQQConfig(): QQConfig { diff --git a/src/main/im/types.ts b/src/main/im/types.ts index 25051ae83c..b9ae41b044 100644 --- a/src/main/im/types.ts +++ b/src/main/im/types.ts @@ -231,7 +231,6 @@ export interface IMGatewayConfig { feishu: FeishuConfig; telegram: TelegramOpenClawConfig; qq: QQConfig; - telegram: TelegramConfig; discord: DiscordConfig; nim: NimConfig; xiaomifeng: XiaomifengConfig; @@ -344,7 +343,7 @@ export type IMConnectivityCheckCode = | 'telegram_privacy_mode_hint' | 'dingtalk_bot_membership_hint' | 'nim_p2p_only_hint' - | 'openclaw_gateway_not_running'; + | 'openclaw_gateway_not_running' | 'qq_guild_mention_hint'; export interface IMConnectivityCheck { @@ -428,6 +427,9 @@ export const DEFAULT_TELEGRAM_OPENCLAW_CONFIG: TelegramOpenClawConfig = { proxy: '', webhookUrl: '', webhookSecret: '', + debug: false, +}; + export const DEFAULT_QQ_CONFIG: QQConfig = { enabled: false, appId: '', @@ -452,7 +454,6 @@ export const DEFAULT_IM_CONFIG: IMGatewayConfig = { feishu: DEFAULT_FEISHU_CONFIG, telegram: DEFAULT_TELEGRAM_OPENCLAW_CONFIG, qq: DEFAULT_QQ_CONFIG, - telegram: DEFAULT_TELEGRAM_CONFIG, discord: DEFAULT_DISCORD_CONFIG, nim: DEFAULT_NIM_CONFIG, xiaomifeng: DEFAULT_XIAOMIFENG_CONFIG, @@ -534,7 +535,6 @@ export const DEFAULT_IM_STATUS: IMGatewayStatus = { lastOutboundAt: null, }, qq: DEFAULT_QQ_STATUS, - telegram: DEFAULT_TELEGRAM_STATUS, discord: DEFAULT_DISCORD_STATUS, nim: DEFAULT_NIM_STATUS, xiaomifeng: DEFAULT_XIAOMIFENG_STATUS, diff --git a/src/main/libs/agentEngine/openclawRuntimeAdapter.ts b/src/main/libs/agentEngine/openclawRuntimeAdapter.ts index 30f238dc76..df48d941af 100644 --- a/src/main/libs/agentEngine/openclawRuntimeAdapter.ts +++ b/src/main/libs/agentEngine/openclawRuntimeAdapter.ts @@ -469,6 +469,8 @@ export class OpenClawRuntimeAdapter extends EventEmitter implements CoworkRuntim private channelSessionSync: OpenClawChannelSessionSync | null = null; private readonly knownChannelSessionIds = new Set(); private readonly fullySyncedSessions = new Set(); + /** Sessions re-created after user deletion — use latestOnly sync to avoid replaying old history. */ + private readonly reCreatedChannelSessionIds = new Set(); /** Channel sessionKeys explicitly deleted by the user. Polling will not re-create these. */ private readonly deletedChannelKeys = new Set(); private channelPollingTimer: ReturnType | null = null; @@ -1225,6 +1227,7 @@ export class OpenClawRuntimeAdapter extends EventEmitter implements CoworkRuntim if (this.deletedChannelKeys.has(sessionKey)) { this.deletedChannelKeys.delete(sessionKey); this.fullySyncedSessions.add(channelSessionId); + this.reCreatedChannelSessionIds.add(channelSessionId); console.log('[Debug:handleAgentEvent] re-created after delete, skipping history sync for:', sessionKey); } this.sessionIdBySessionKey.set(sessionKey, channelSessionId); @@ -1915,6 +1918,7 @@ export class OpenClawRuntimeAdapter extends EventEmitter implements CoworkRuntim if (this.deletedChannelKeys.has(sessionKey)) { this.deletedChannelKeys.delete(sessionKey); this.fullySyncedSessions.add(channelSessionId); + this.reCreatedChannelSessionIds.add(channelSessionId); console.log('[Debug:resolveSessionId] re-created after delete, skipping history sync for:', sessionKey); } this.sessionIdBySessionKey.set(sessionKey, channelSessionId); @@ -1980,7 +1984,7 @@ export class OpenClawRuntimeAdapter extends EventEmitter implements CoworkRuntim && !turn.sessionKey.startsWith('lobsterai:') && this.channelSessionSync.isChannelSessionKey(turn.sessionKey); if (isChannel) { - const latestOnly = this.fullySyncedSessions.has(sessionId); + const latestOnly = this.reCreatedChannelSessionIds.has(sessionId); this.syncChannelUserMessages(sessionId, history.messages, latestOnly); } @@ -2247,6 +2251,7 @@ export class OpenClawRuntimeAdapter extends EventEmitter implements CoworkRuntim } this.activeTurns.delete(sessionId); this.lastSystemPromptBySession.delete(sessionId); + this.reCreatedChannelSessionIds.delete(sessionId); } /** @@ -2275,6 +2280,7 @@ export class OpenClawRuntimeAdapter extends EventEmitter implements CoworkRuntim // Allow full history re-sync when session is re-created this.fullySyncedSessions.delete(sessionId); + this.reCreatedChannelSessionIds.delete(sessionId); // Clean up active turn and related run-id mappings this.cleanupSessionTurn(sessionId); @@ -2358,7 +2364,7 @@ export class OpenClawRuntimeAdapter extends EventEmitter implements CoworkRuntim console.log('[Debug:prefetch] chat.history returned', msgCount, 'messages (attempt', attempt, ')'); if (Array.isArray(history?.messages) && history.messages.length > 0) { - const latestOnly = this.fullySyncedSessions.has(sessionId); + const latestOnly = this.reCreatedChannelSessionIds.has(sessionId); const beforeCount = this.getUserMessageCount(sessionId); this.syncChannelUserMessages(sessionId, history.messages, latestOnly); const afterCount = this.getUserMessageCount(sessionId); diff --git a/src/main/main.ts b/src/main/main.ts index 2f92013565..f847fcea92 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -675,6 +675,10 @@ const getOpenClawConfigSync = (): OpenClawConfigSync => { getTelegramOpenClawConfig: () => { try { return getIMGatewayManager()?.getConfig()?.telegram ?? null; + } catch { + return null; + } + }, getDingTalkConfig: () => { try { return getIMGatewayManager().getConfig().dingtalk; diff --git a/src/renderer/components/im/IMSettings.tsx b/src/renderer/components/im/IMSettings.tsx index 9ad6f0bd22..004ec315c7 100644 --- a/src/renderer/components/im/IMSettings.tsx +++ b/src/renderer/components/im/IMSettings.tsx @@ -9,8 +9,7 @@ import { SignalIcon, XMarkIcon, CheckCircleIcon, XCircleIcon, ExclamationTriangl import { EyeIcon, EyeSlashIcon, XCircleIcon as XCircleIconSolid } from '@heroicons/react/20/solid'; import { RootState } from '../../store'; import { imService } from '../../services/im'; -import { setDingTalkConfig, setFeishuConfig, setTelegramOpenClawConfig, setDiscordConfig, setNimConfig, setXiaomifengConfig, clearError } from '../../store/slices/imSlice'; -import { setDingTalkConfig, setFeishuConfig, setQQConfig, setTelegramConfig, setDiscordConfig, setNimConfig, setXiaomifengConfig, setWecomConfig, clearError } from '../../store/slices/imSlice'; +import { setDingTalkConfig, setFeishuConfig, setTelegramOpenClawConfig, setQQConfig, setDiscordConfig, setNimConfig, setXiaomifengConfig, setWecomConfig, clearError } from '../../store/slices/imSlice'; import { i18nService } from '../../services/i18n'; import type { IMPlatform, IMConnectivityCheck, IMConnectivityTestResult, IMGatewayConfig, TelegramOpenClawConfig } from '../../types/im'; import { getVisibleIMPlatforms } from '../../utils/regionFilter'; @@ -126,14 +125,16 @@ const IMSettings: React.FC = () => { ? { ...tgOpenClawConfig, ...override } : tgOpenClawConfig; await imService.updateConfig({ telegram: configToSave }); + }; + // Handle QQ config change const handleQQChange = (field: 'appId' | 'appSecret', value: string) => { dispatch(setQQConfig({ [field]: value })); }; - // Handle Telegram config change - const handleTelegramChange = (field: 'botToken' | 'allowedUserIds', value: string | string[]) => { - dispatch(setTelegramConfig({ [field]: value })); + // Handle Telegram OpenClaw config change (legacy wrapper) + const handleTelegramChange = (field: string, value: string | string[]) => { + dispatch(setTelegramOpenClawConfig({ [field]: value })); }; // Handle Discord config change @@ -443,7 +444,6 @@ const IMSettings: React.FC = () => { feishu: setFeishuConfig, telegram: setTelegramOpenClawConfig, qq: setQQConfig, - telegram: setTelegramConfig, discord: setDiscordConfig, nim: setNimConfig, xiaomifeng: setXiaomifengConfig, diff --git a/src/renderer/store/slices/imSlice.ts b/src/renderer/store/slices/imSlice.ts index 9a328a90eb..dd6c9a158b 100644 --- a/src/renderer/store/slices/imSlice.ts +++ b/src/renderer/store/slices/imSlice.ts @@ -11,7 +11,6 @@ import type { FeishuConfig, TelegramOpenClawConfig, QQConfig, - TelegramConfig, DiscordConfig, NimConfig, XiaomifengConfig, @@ -55,12 +54,10 @@ const imSlice = createSlice({ ...state.config.telegram, ...action.payload, }; + }, setQQConfig: (state, action: PayloadAction>) => { state.config.qq = { ...state.config.qq, ...action.payload }; }, - setTelegramConfig: (state, action: PayloadAction>) => { - state.config.telegram = { ...state.config.telegram, ...action.payload }; - }, setDiscordConfig: (state, action: PayloadAction>) => { state.config.discord = { ...state.config.discord, ...action.payload }; }, @@ -97,7 +94,6 @@ export const { setFeishuConfig, setTelegramOpenClawConfig, setQQConfig, - setTelegramConfig, setDiscordConfig, setNimConfig, setXiaomifengConfig, diff --git a/src/renderer/types/electron.d.ts b/src/renderer/types/electron.d.ts index 7c1369170a..2af6a3ea02 100644 --- a/src/renderer/types/electron.d.ts +++ b/src/renderer/types/electron.d.ts @@ -447,7 +447,6 @@ interface IMGatewayConfig { feishu: FeishuConfig; telegram: TelegramOpenClawConfig; qq: QQConfig; - telegram: TelegramConfig; discord: DiscordConfig; nim: NimConfig; xiaomifeng: XiaomifengConfig; diff --git a/src/renderer/types/im.ts b/src/renderer/types/im.ts index 39f30291bc..b68a361b9d 100644 --- a/src/renderer/types/im.ts +++ b/src/renderer/types/im.ts @@ -193,7 +193,6 @@ export interface IMGatewayConfig { feishu: FeishuConfig; telegram: TelegramOpenClawConfig; qq: QQConfig; - telegram: TelegramConfig; discord: DiscordConfig; nim: NimConfig; xiaomifeng: XiaomifengConfig; @@ -283,7 +282,7 @@ export type IMConnectivityCheckCode = | 'telegram_privacy_mode_hint' | 'dingtalk_bot_membership_hint' | 'nim_p2p_only_hint' - | 'openclaw_gateway_not_running'; + | 'openclaw_gateway_not_running' | 'qq_guild_mention_hint'; export interface IMConnectivityCheck { @@ -363,6 +362,9 @@ export const DEFAULT_TELEGRAM_OPENCLAW_CONFIG: TelegramOpenClawConfig = { proxy: '', webhookUrl: '', webhookSecret: '', + debug: false, +}; + export const DEFAULT_QQ_CONFIG: QQConfig = { enabled: false, appId: '', @@ -387,7 +389,6 @@ export const DEFAULT_IM_CONFIG: IMGatewayConfig = { feishu: DEFAULT_FEISHU_CONFIG, telegram: DEFAULT_TELEGRAM_OPENCLAW_CONFIG, qq: DEFAULT_QQ_CONFIG, - telegram: DEFAULT_TELEGRAM_CONFIG, discord: DEFAULT_DISCORD_CONFIG, nim: DEFAULT_NIM_CONFIG, xiaomifeng: DEFAULT_XIAOMIFENG_CONFIG,