Skip to content

Commit d133f28

Browse files
steipeteobviyus
andauthored
fix: preserve selected models through hot reloads and fallbacks (#103510)
* fix(agents): keep model fallback turn-local instead of persisting over user pins * fix(telegram): use live config snapshots per operation Co-authored-by: Ayaan Zaidi <[email protected]> * test(telegram): fix config snapshot type coverage --------- Co-authored-by: Ayaan Zaidi <[email protected]>
1 parent 195bec6 commit d133f28

26 files changed

Lines changed: 620 additions & 1142 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Docs: https://docs.openclaw.ai
2525

2626
### Fixes
2727

28+
- **Model pin hot reload and fallback:** keep explicit `/model` selections authoritative across Telegram config reloads and model fallback, capture one live config snapshot per assembled turn, and leave fallback candidates turn-local instead of persisting them over the user's pin. (#103324, #103417) Thanks @obviyus.
2829
- **Swift protocol initializers:** default every schema-optional generated initializer parameter to `nil` so additive protocol fields no longer break SDK construction call sites.
2930
- **OpenCode Go MiMo catalog:** stop exposing the deprecated `mimo-v2-omni` and `mimo-v2-pro` aliases that reject agent requests, and keep release validation on the active MiMo V2.5 routes. (#103311, #103329) Thanks @krissding.
3031
- **OpenAI-compatible streamed tool calls:** execute complete native tool calls from streams that end with SSE `data: [DONE]` but omit `finish_reason`, while keeping transport EOF and visible-text cases fail-closed. (#98124, #97994) Thanks @SunnyShu0925.

extensions/telegram/src/bot-core.ts

Lines changed: 30 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
resolveChannelGroupPolicy,
44
resolveChannelGroupRequireMention,
55
} from "openclaw/plugin-sdk/channel-policy";
6+
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
67
import {
78
resolveThreadBindingIdleTimeoutMsForChannel,
89
resolveThreadBindingMaxAgeMsForChannel,
@@ -14,8 +15,7 @@ import {
1415
resolveNativeCommandsEnabled,
1516
resolveNativeSkillsEnabled,
1617
} from "openclaw/plugin-sdk/native-command-config-runtime";
17-
import { resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-chunking";
18-
import { DEFAULT_GROUP_HISTORY_LIMIT, type HistoryEntry } from "openclaw/plugin-sdk/reply-history";
18+
import type { HistoryEntry } from "openclaw/plugin-sdk/reply-history";
1919
import { danger, logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
2020
import { getChildLogger } from "openclaw/plugin-sdk/runtime-env";
2121
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
@@ -26,7 +26,10 @@ import { resolveTelegramAccount } from "./accounts.js";
2626
import { normalizeTelegramApiRoot } from "./api-root.js";
2727
import type { TelegramBotDeps } from "./bot-deps.js";
2828
import { registerTelegramHandlers } from "./bot-handlers.runtime.js";
29-
import { createTelegramMessageProcessor } from "./bot-message.js";
29+
import {
30+
createTelegramMessageProcessor,
31+
resolveTelegramMessageTurnSettings,
32+
} from "./bot-message.js";
3033
import { registerTelegramNativeCommands } from "./bot-native-commands.js";
3134
import {
3235
getTelegramSpooledReplayDeferredParticipant,
@@ -39,7 +42,7 @@ import type { TelegramUpdateKeyContext } from "./bot-updates.js";
3942
import { resolveDefaultAgentId } from "./bot.agent.runtime.js";
4043
import { apiThrottler, Bot, sequentialize, type ApiClientOptions } from "./bot.runtime.js";
4144
import type { TelegramBotOptions } from "./bot.types.js";
42-
import { buildTelegramGroupPeerId, resolveTelegramStreamMode } from "./bot/helpers.js";
45+
import { buildTelegramGroupPeerId } from "./bot/helpers.js";
4346
import { setTelegramCallbackQueryAnswerPromise } from "./callback-query-answer-state.js";
4447
import {
4548
asTelegramClientFetch,
@@ -54,10 +57,8 @@ import {
5457
buildTelegramGroupHistorySelfSender,
5558
recordTelegramGroupHistoryEntry,
5659
} from "./group-history-window.js";
57-
import { TELEGRAM_TEXT_CHUNK_LIMIT } from "./outbound-adapter.js";
5860
import { registerTelegramOutboundGroupHistoryRecorder } from "./outbound-message-context.js";
5961
import { formatTelegramRawUpdateForLog } from "./raw-update-log.js";
60-
import { TELEGRAM_RICH_TEXT_LIMIT } from "./rich-message.js";
6162
import { createTelegramSendChatActionHandler } from "./sendchataction-401-backoff.js";
6263
import { getTelegramSequentialKey } from "./sequential-key.js";
6364
import { createTelegramThreadBindingManager } from "./thread-bindings.js";
@@ -253,12 +254,12 @@ export function createTelegramBotCore(
253254
await next();
254255
});
255256

256-
const historyLimit = Math.max(
257-
0,
258-
telegramCfg.historyLimit ??
259-
cfg.messages?.groupChat?.historyLimit ??
260-
DEFAULT_GROUP_HISTORY_LIMIT,
261-
);
257+
const { historyLimit } = resolveTelegramMessageTurnSettings({
258+
accountId: account.accountId,
259+
cfg,
260+
telegramCfg,
261+
opts,
262+
});
262263
const groupHistories = new Map<string, HistoryEntry[]>();
263264
const botHistorySender = buildTelegramGroupHistorySelfSender(
264265
account.name ?? opts.botInfo?.first_name ?? opts.botInfo?.username ?? "OpenClaw",
@@ -282,19 +283,6 @@ export function createTelegramBotCore(
282283
});
283284
},
284285
});
285-
const telegramTextLimit =
286-
telegramCfg.richMessages === true ? TELEGRAM_RICH_TEXT_LIMIT : TELEGRAM_TEXT_CHUNK_LIMIT;
287-
const textLimit = Math.min(
288-
resolveTextChunkLimit(cfg, "telegram", account.accountId, {
289-
fallbackLimit: telegramTextLimit,
290-
}),
291-
telegramTextLimit,
292-
);
293-
const dmPolicy = telegramCfg.dmPolicy ?? "pairing";
294-
const allowFrom = opts.allowFrom ?? telegramCfg.allowFrom;
295-
const groupAllowFrom =
296-
opts.groupAllowFrom ?? telegramCfg.groupAllowFrom ?? telegramCfg.allowFrom ?? allowFrom;
297-
const replyToMode = opts.replyToMode ?? telegramCfg.replyToMode ?? "off";
298286
const nativeEnabled = resolveNativeCommandsEnabled({
299287
providerId: "telegram",
300288
providerSetting: telegramCfg.commands?.native,
@@ -309,14 +297,11 @@ export function createTelegramBotCore(
309297
providerSetting: telegramCfg.commands?.native,
310298
globalSetting: cfg.commands?.native,
311299
});
312-
const useAccessGroups = cfg.commands?.useAccessGroups !== false;
313-
const ackReactionScope = cfg.messages?.ackReactionScope ?? "group-mentions";
314300
const mediaMaxBytes = (opts.mediaMaxMb ?? telegramCfg.mediaMaxMb ?? 100) * 1024 * 1024;
315301
const logger = getChildLogger({ module: "telegram-auto-reply" });
316-
const streamMode = resolveTelegramStreamMode(telegramCfg);
317-
const resolveGroupPolicy = (chatId: string | number) =>
302+
const resolveGroupPolicy = (chatId: string | number, turnCfg: OpenClawConfig) =>
318303
resolveChannelGroupPolicy({
319-
cfg,
304+
cfg: turnCfg,
320305
channel: "telegram",
321306
accountId: account.accountId,
322307
groupId: String(chatId),
@@ -326,12 +311,13 @@ export function createTelegramBotCore(
326311
agentId?: string;
327312
messageThreadId?: number;
328313
sessionKey?: string;
314+
cfg: OpenClawConfig;
329315
}) => {
330-
const agentId = params.agentId ?? resolveDefaultAgentId(cfg);
316+
const agentId = params.agentId ?? resolveDefaultAgentId(params.cfg);
331317
const sessionKey =
332318
params.sessionKey ??
333319
`agent:${agentId}:telegram:group:${buildTelegramGroupPeerId(params.chatId, params.messageThreadId)}`;
334-
const storePath = telegramDeps.resolveStorePath(cfg.session?.store, { agentId });
320+
const storePath = telegramDeps.resolveStorePath(params.cfg.session?.store, { agentId });
335321
try {
336322
const getSessionEntry = telegramDeps.getSessionEntry;
337323
if (!getSessionEntry) {
@@ -349,31 +335,25 @@ export function createTelegramBotCore(
349335
}
350336
return undefined;
351337
};
352-
const resolveGroupRequireMention = (chatId: string | number) =>
338+
const resolveGroupRequireMention = (chatId: string | number, turnCfg: OpenClawConfig) =>
353339
resolveChannelGroupRequireMention({
354-
cfg,
340+
cfg: turnCfg,
355341
channel: "telegram",
356342
accountId: account.accountId,
357343
groupId: String(chatId),
358344
requireMentionOverride: opts.requireMention,
359345
overrideOrder: "after-config",
360346
});
361-
const loadFreshTelegramAccountConfig = () => {
362-
try {
363-
return resolveTelegramAccount({
364-
cfg: telegramDeps.getRuntimeConfig(),
365-
accountId: account.accountId,
366-
}).config;
367-
} catch (error) {
368-
logVerbose(
369-
`telegram: failed to load fresh config for account ${account.accountId}; using startup snapshot: ${String(error)}`,
370-
);
371-
return telegramCfg;
372-
}
373-
};
374-
const resolveTelegramGroupConfig = (chatId: string | number, messageThreadId?: number) => {
375-
const freshTelegramCfg = loadFreshTelegramAccountConfig();
376-
return resolveTelegramScopedGroupConfig(freshTelegramCfg, chatId, messageThreadId);
347+
const resolveTelegramGroupConfig = (
348+
chatId: string | number,
349+
messageThreadId: number | undefined,
350+
turnCfg: OpenClawConfig,
351+
) => {
352+
const turnTelegramCfg = resolveTelegramAccount({
353+
cfg: turnCfg,
354+
accountId: account.accountId,
355+
}).config;
356+
return resolveTelegramScopedGroupConfig(turnTelegramCfg, chatId, messageThreadId);
377357
};
378358

379359
// Global sendChatAction handler with 401 backoff and transient cooldown.
@@ -389,25 +369,14 @@ export function createTelegramBotCore(
389369

390370
const processMessage = createTelegramMessageProcessor({
391371
bot,
392-
cfg,
393372
account,
394-
telegramCfg,
395-
historyLimit,
396373
groupHistories,
397-
dmPolicy,
398-
allowFrom,
399-
groupAllowFrom,
400-
ackReactionScope,
401374
logger,
402375
resolveGroupActivation,
403376
resolveGroupRequireMention,
404377
resolveTelegramGroupConfig,
405-
loadFreshConfig: () => telegramDeps.getRuntimeConfig(),
406378
sendChatActionHandler,
407379
runtime,
408-
replyToMode,
409-
streamMode,
410-
textLimit,
411380
opts,
412381
telegramDeps,
413382
});
@@ -418,12 +387,7 @@ export function createTelegramBotCore(
418387
runtime,
419388
accountId: account.accountId,
420389
telegramCfg,
421-
allowFrom,
422-
groupAllowFrom,
423-
replyToMode,
424-
textLimit,
425390
mediaMaxBytes,
426-
useAccessGroups,
427391
nativeEnabled,
428392
nativeSkillsEnabled,
429393
nativeDisabledExplicit,
@@ -443,8 +407,6 @@ export function createTelegramBotCore(
443407
runtime,
444408
mediaMaxBytes,
445409
telegramCfg,
446-
allowFrom,
447-
groupAllowFrom,
448410
resolveGroupPolicy,
449411
resolveGroupActivation,
450412
resolveGroupRequireMention,

0 commit comments

Comments
 (0)