diff --git a/extensions/telegram/src/bot-message-context.dm-threads.test.ts b/extensions/telegram/src/bot-message-context.dm-threads.test.ts index 6efd0e0d2f9..f11af44f791 100644 --- a/extensions/telegram/src/bot-message-context.dm-threads.test.ts +++ b/extensions/telegram/src/bot-message-context.dm-threads.test.ts @@ -3,8 +3,9 @@ import os from "node:os"; import path from "node:path"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { resetTopicNameCacheForTest } from "./topic-name-cache.js"; -const { recordInboundSessionMock } = vi.hoisted(() => ({ +const { recordInboundSessionMock, resolveStorePathMock } = vi.hoisted(() => ({ recordInboundSessionMock: vi.fn().mockResolvedValue(undefined), + resolveStorePathMock: vi.fn(() => "/tmp/openclaw-session-store.json"), })); vi.mock("./bot-message-context.session.runtime.js", async () => { @@ -14,6 +15,7 @@ vi.mock("./bot-message-context.session.runtime.js", async () => { return { ...actual, recordInboundSession: (...args: unknown[]) => recordInboundSessionMock(...args), + resolveStorePath: (...args: unknown[]) => resolveStorePathMock(...args), }; }); @@ -45,6 +47,8 @@ afterEach(() => { clearRuntimeConfigSnapshot(); resetTopicNameCacheForTest(); recordInboundSessionMock.mockClear(); + resolveStorePathMock.mockReset(); + resolveStorePathMock.mockReturnValue("/tmp/openclaw-session-store.json"); }); describe("buildTelegramMessageContext dm thread sessions", () => { @@ -236,6 +240,54 @@ describe("buildTelegramMessageContext group sessions without forum", () => { resetTopicNameCacheForTest(); } }); + + it("persists topic names through the default session runtime path", async () => { + const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-telegram-topic-name-")); + const sessionStorePath = path.join(tempDir, "sessions.json"); + resolveStorePathMock.mockReturnValue(sessionStorePath); + + try { + await buildTelegramMessageContextForTest({ + message: { + message_id: 6, + chat: { id: -1001234567890, type: "supergroup", title: "Test Forum", is_forum: true }, + date: 1700000005, + text: "@bot hello", + message_thread_id: 99, + from: { id: 42, first_name: "Alice" }, + reply_to_message: { + message_id: 5, + forum_topic_created: { name: "Deployments", icon_color: 0x6fb9f0 }, + }, + }, + options: { forceWasMentioned: true }, + resolveGroupActivation: () => true, + sessionRuntime: null, + }); + + resetTopicNameCacheForTest(); + + const ctx = await buildTelegramMessageContextForTest({ + message: { + message_id: 7, + chat: { id: -1001234567890, type: "supergroup", title: "Test Forum", is_forum: true }, + date: 1700000006, + text: "@bot again", + message_thread_id: 99, + from: { id: 42, first_name: "Alice" }, + }, + options: { forceWasMentioned: true }, + resolveGroupActivation: () => true, + sessionRuntime: null, + }); + + expect(ctx).not.toBeNull(); + expect(ctx?.ctxPayload?.TopicName).toBe("Deployments"); + } finally { + await fs.rm(tempDir, { recursive: true, force: true }); + resetTopicNameCacheForTest(); + } + }); }); describe("buildTelegramMessageContext direct peer routing", () => { diff --git a/extensions/telegram/src/bot-message-context.session.ts b/extensions/telegram/src/bot-message-context.session.ts index 33f45babc21..23491d253ab 100644 --- a/extensions/telegram/src/bot-message-context.session.ts +++ b/extensions/telegram/src/bot-message-context.session.ts @@ -76,6 +76,17 @@ async function loadTelegramMessageContextSessionRuntime( }; } +export async function resolveTelegramMessageContextStorePath(params: { + cfg: OpenClawConfig; + agentId: string; + sessionRuntime?: TelegramMessageContextSessionRuntimeOverrides; +}): Promise { + const sessionRuntime = await loadTelegramMessageContextSessionRuntime(params.sessionRuntime); + return sessionRuntime.resolveStorePath(params.cfg.session?.store, { + agentId: params.agentId, + }); +} + export async function buildTelegramInboundContextPayload(params: { cfg: OpenClawConfig; primaryCtx: TelegramContext; @@ -232,8 +243,10 @@ export async function buildTelegramInboundContextPayload(params: { ? (groupLabel ?? `group:${chatId}`) : buildSenderLabel(msg, senderId || chatId); const sessionRuntime = await loadTelegramMessageContextSessionRuntime(sessionRuntimeOverride); - const storePath = sessionRuntime.resolveStorePath(cfg.session?.store, { + const storePath = await resolveTelegramMessageContextStorePath({ + cfg, agentId: route.agentId, + sessionRuntime: sessionRuntimeOverride, }); const envelopeOptions = resolveEnvelopeFormatOptions(cfg); const previousTimestamp = sessionRuntime.readSessionUpdatedAt({ diff --git a/extensions/telegram/src/bot-message-context.ts b/extensions/telegram/src/bot-message-context.ts index 7bd40b5dcac..55dda165ce3 100644 --- a/extensions/telegram/src/bot-message-context.ts +++ b/extensions/telegram/src/bot-message-context.ts @@ -11,7 +11,10 @@ import { logVerbose } from "openclaw/plugin-sdk/runtime-env"; import { withTelegramApiErrorLogging } from "./api-logging.js"; import { firstDefined, normalizeAllowFrom, normalizeDmAllowFromWithStore } from "./bot-access.js"; import { resolveTelegramInboundBody } from "./bot-message-context.body.js"; -import { buildTelegramInboundContextPayload } from "./bot-message-context.session.js"; +import { + buildTelegramInboundContextPayload, + resolveTelegramMessageContextStorePath, +} from "./bot-message-context.session.js"; import type { BuildTelegramMessageContextParams } from "./bot-message-context.types.js"; import { buildTypingThreadParams, @@ -149,11 +152,13 @@ export const buildTelegramMessageContext = async ({ const resolvedThreadId = threadSpec.scope === "forum" ? threadSpec.id : undefined; const replyThreadId = threadSpec.id; const dmThreadId = threadSpec.scope === "dm" ? threadSpec.id : undefined; - const topicNameCachePath = sessionRuntime?.resolveStorePath - ? resolveTopicNameCachePath( - sessionRuntime.resolveStorePath(cfg.session?.store, { agentId: account.accountId }), - ) - : undefined; + const topicNameCachePath = resolveTopicNameCachePath( + await resolveTelegramMessageContextStorePath({ + cfg, + agentId: account.accountId, + sessionRuntime, + }), + ); let topicName: string | undefined; if (isForum && resolvedThreadId != null) { const ftCreated = msg.forum_topic_created;