diff --git a/CHANGELOG.md b/CHANGELOG.md index e359d8987a0..df8a091e61d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,6 +76,7 @@ Docs: https://docs.openclaw.ai - active-memory: skip the memory sub-agent gracefully instead of logging a confusing allowlist error when no memory plugin (`memory-core` or `memory-lancedb`) is loaded, so active-memory with no memory backend no longer produces misleading "No callable tools remain" warnings in the gateway log. Fixes #77506. Thanks @hclsys. - Memory/wiki: preserve representation from both corpora in `corpus=all` searches while backfilling unused result capacity, so memory hits are not starved by numerically higher wiki integer scores. Fixes #77337. Thanks @hclsys. - Telegram: clean up tool-only draft previews after assistant message boundaries so transient `Surfacing...` tool-status bubbles do not linger when no matching final preview arrives. Thanks @BunsDev. +- Telegram: let explicit forum-topic `requireMention` settings override persisted `/activate` and `/deactivate` state, so per-topic mention gates work consistently. Fixes #49864. Thanks @Panniantong. - Cron: surface failed isolated-run diagnostics in `cron show`, status, and run history when requested tools are unavailable, so blocked cron runs report the actual tool-policy failure instead of a misleading green result. Fixes #75763. Thanks @RyanSandoval. - TUI/escape abort: track the in-flight runId after `chat.send` resolves so pressing Esc during the gap before the first gateway event aborts the run instead of repeatedly printing `no active run`. Fixes #1296. Thanks @Lukavyi and @romneyda. - TUI/render: stop the long-token sanitizer from injecting literal spaces inside inline code spans, fenced code blocks, table borders, and bare hyphenated/dotted identifiers, so copied package names, entity IDs, and shell line-continuations stay byte-for-byte intact while narrow-terminal protection still chunks unidentifiable long prose tokens. Fixes #48432, #39505. Thanks @DocOellerson, @xeusoc, @CCcassiusdjs, @akramcodez, @brokemac79, @romneyda. diff --git a/extensions/telegram/src/bot-message-context.require-mention.test.ts b/extensions/telegram/src/bot-message-context.require-mention.test.ts new file mode 100644 index 00000000000..deed88a9901 --- /dev/null +++ b/extensions/telegram/src/bot-message-context.require-mention.test.ts @@ -0,0 +1,112 @@ +import { getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const { defaultRouteConfig } = vi.hoisted(() => ({ + defaultRouteConfig: { + agents: { + list: [{ id: "main", default: true }], + }, + channels: { telegram: {} }, + messages: { groupChat: { mentionPatterns: [] } }, + }, +})); + +vi.mock("openclaw/plugin-sdk/runtime-config-snapshot", async () => { + const actual = await vi.importActual< + typeof import("openclaw/plugin-sdk/runtime-config-snapshot") + >("openclaw/plugin-sdk/runtime-config-snapshot"); + return { + ...actual, + getRuntimeConfig: vi.fn(() => defaultRouteConfig), + }; +}); + +const { buildTelegramMessageContextForTest } = + await import("./bot-message-context.test-harness.js"); + +describe("buildTelegramMessageContext requireMention precedence", () => { + function buildForumMessage(threadId = 99) { + return { + message_id: 1, + chat: { + id: -1001234567890, + type: "supergroup" as const, + title: "Forum", + is_forum: true, + }, + date: 1_700_000_000, + text: "hello everyone", + message_thread_id: threadId, + from: { id: 42, first_name: "Alice" }, + }; + } + + beforeEach(() => { + vi.mocked(getRuntimeConfig).mockReturnValue(defaultRouteConfig as never); + }); + + it("lets explicit topic requireMention=false override group requireMention=true", async () => { + const ctx = await buildTelegramMessageContextForTest({ + message: buildForumMessage(), + resolveGroupActivation: () => undefined, + resolveGroupRequireMention: () => true, + resolveTelegramGroupConfig: () => ({ + groupConfig: { requireMention: true }, + topicConfig: { requireMention: false }, + }), + }); + + expect(ctx).not.toBeNull(); + }); + + it("lets explicit topic requireMention=false override mention activation", async () => { + const resolveGroupActivation = vi.fn(() => true); + + const ctx = await buildTelegramMessageContextForTest({ + message: buildForumMessage(), + resolveGroupActivation, + resolveGroupRequireMention: () => true, + resolveTelegramGroupConfig: () => ({ + groupConfig: { requireMention: true }, + topicConfig: { requireMention: false }, + }), + }); + + expect(ctx).not.toBeNull(); + expect(resolveGroupActivation).toHaveBeenCalledWith( + expect.objectContaining({ + chatId: -1001234567890, + messageThreadId: 99, + sessionKey: "agent:main:telegram:group:-1001234567890:topic:99", + }), + ); + }); + + it("lets explicit topic requireMention=true override always activation", async () => { + const ctx = await buildTelegramMessageContextForTest({ + message: buildForumMessage(), + resolveGroupActivation: () => false, + resolveGroupRequireMention: () => false, + resolveTelegramGroupConfig: () => ({ + groupConfig: { requireMention: false }, + topicConfig: { requireMention: true }, + }), + }); + + expect(ctx).toBeNull(); + }); + + it("keeps activation fallback when no topic requireMention is configured", async () => { + const ctx = await buildTelegramMessageContextForTest({ + message: buildForumMessage(), + resolveGroupActivation: () => false, + resolveGroupRequireMention: () => true, + resolveTelegramGroupConfig: () => ({ + groupConfig: { requireMention: true }, + topicConfig: { agentId: "main" }, + }), + }); + + expect(ctx).not.toBeNull(); + }); +}); diff --git a/extensions/telegram/src/bot-message-context.ts b/extensions/telegram/src/bot-message-context.ts index d7c44e39587..e969c668161 100644 --- a/extensions/telegram/src/bot-message-context.ts +++ b/extensions/telegram/src/bot-message-context.ts @@ -411,8 +411,8 @@ export const buildTelegramMessageContext = async ({ }); const baseRequireMention = resolveGroupRequireMention(chatId); const requireMention = firstDefined( - activationOverride, topicConfig?.requireMention, + activationOverride, telegramGroupConfig?.requireMention, baseRequireMention, );