Skip to content

Commit c91d3d4

Browse files
committed
fix(telegram): persist topic cache via default runtime
1 parent 4f92b1f commit c91d3d4

3 files changed

Lines changed: 78 additions & 8 deletions

File tree

extensions/telegram/src/bot-message-context.dm-threads.test.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import os from "node:os";
33
import path from "node:path";
44
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
55
import { resetTopicNameCacheForTest } from "./topic-name-cache.js";
6-
const { recordInboundSessionMock } = vi.hoisted(() => ({
6+
const { recordInboundSessionMock, resolveStorePathMock } = vi.hoisted(() => ({
77
recordInboundSessionMock: vi.fn().mockResolvedValue(undefined),
8+
resolveStorePathMock: vi.fn(() => "/tmp/openclaw-session-store.json"),
89
}));
910

1011
vi.mock("./bot-message-context.session.runtime.js", async () => {
@@ -14,6 +15,7 @@ vi.mock("./bot-message-context.session.runtime.js", async () => {
1415
return {
1516
...actual,
1617
recordInboundSession: (...args: unknown[]) => recordInboundSessionMock(...args),
18+
resolveStorePath: (...args: unknown[]) => resolveStorePathMock(...args),
1719
};
1820
});
1921

@@ -45,6 +47,8 @@ afterEach(() => {
4547
clearRuntimeConfigSnapshot();
4648
resetTopicNameCacheForTest();
4749
recordInboundSessionMock.mockClear();
50+
resolveStorePathMock.mockReset();
51+
resolveStorePathMock.mockReturnValue("/tmp/openclaw-session-store.json");
4852
});
4953

5054
describe("buildTelegramMessageContext dm thread sessions", () => {
@@ -236,6 +240,54 @@ describe("buildTelegramMessageContext group sessions without forum", () => {
236240
resetTopicNameCacheForTest();
237241
}
238242
});
243+
244+
it("persists topic names through the default session runtime path", async () => {
245+
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-telegram-topic-name-"));
246+
const sessionStorePath = path.join(tempDir, "sessions.json");
247+
resolveStorePathMock.mockReturnValue(sessionStorePath);
248+
249+
try {
250+
await buildTelegramMessageContextForTest({
251+
message: {
252+
message_id: 6,
253+
chat: { id: -1001234567890, type: "supergroup", title: "Test Forum", is_forum: true },
254+
date: 1700000005,
255+
text: "@bot hello",
256+
message_thread_id: 99,
257+
from: { id: 42, first_name: "Alice" },
258+
reply_to_message: {
259+
message_id: 5,
260+
forum_topic_created: { name: "Deployments", icon_color: 0x6fb9f0 },
261+
},
262+
},
263+
options: { forceWasMentioned: true },
264+
resolveGroupActivation: () => true,
265+
sessionRuntime: null,
266+
});
267+
268+
resetTopicNameCacheForTest();
269+
270+
const ctx = await buildTelegramMessageContextForTest({
271+
message: {
272+
message_id: 7,
273+
chat: { id: -1001234567890, type: "supergroup", title: "Test Forum", is_forum: true },
274+
date: 1700000006,
275+
text: "@bot again",
276+
message_thread_id: 99,
277+
from: { id: 42, first_name: "Alice" },
278+
},
279+
options: { forceWasMentioned: true },
280+
resolveGroupActivation: () => true,
281+
sessionRuntime: null,
282+
});
283+
284+
expect(ctx).not.toBeNull();
285+
expect(ctx?.ctxPayload?.TopicName).toBe("Deployments");
286+
} finally {
287+
await fs.rm(tempDir, { recursive: true, force: true });
288+
resetTopicNameCacheForTest();
289+
}
290+
});
239291
});
240292

241293
describe("buildTelegramMessageContext direct peer routing", () => {

extensions/telegram/src/bot-message-context.session.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,17 @@ async function loadTelegramMessageContextSessionRuntime(
7676
};
7777
}
7878

79+
export async function resolveTelegramMessageContextStorePath(params: {
80+
cfg: OpenClawConfig;
81+
agentId: string;
82+
sessionRuntime?: TelegramMessageContextSessionRuntimeOverrides;
83+
}): Promise<string> {
84+
const sessionRuntime = await loadTelegramMessageContextSessionRuntime(params.sessionRuntime);
85+
return sessionRuntime.resolveStorePath(params.cfg.session?.store, {
86+
agentId: params.agentId,
87+
});
88+
}
89+
7990
export async function buildTelegramInboundContextPayload(params: {
8091
cfg: OpenClawConfig;
8192
primaryCtx: TelegramContext;
@@ -232,8 +243,10 @@ export async function buildTelegramInboundContextPayload(params: {
232243
? (groupLabel ?? `group:${chatId}`)
233244
: buildSenderLabel(msg, senderId || chatId);
234245
const sessionRuntime = await loadTelegramMessageContextSessionRuntime(sessionRuntimeOverride);
235-
const storePath = sessionRuntime.resolveStorePath(cfg.session?.store, {
246+
const storePath = await resolveTelegramMessageContextStorePath({
247+
cfg,
236248
agentId: route.agentId,
249+
sessionRuntime: sessionRuntimeOverride,
237250
});
238251
const envelopeOptions = resolveEnvelopeFormatOptions(cfg);
239252
const previousTimestamp = sessionRuntime.readSessionUpdatedAt({

extensions/telegram/src/bot-message-context.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
1111
import { withTelegramApiErrorLogging } from "./api-logging.js";
1212
import { firstDefined, normalizeAllowFrom, normalizeDmAllowFromWithStore } from "./bot-access.js";
1313
import { resolveTelegramInboundBody } from "./bot-message-context.body.js";
14-
import { buildTelegramInboundContextPayload } from "./bot-message-context.session.js";
14+
import {
15+
buildTelegramInboundContextPayload,
16+
resolveTelegramMessageContextStorePath,
17+
} from "./bot-message-context.session.js";
1518
import type { BuildTelegramMessageContextParams } from "./bot-message-context.types.js";
1619
import {
1720
buildTypingThreadParams,
@@ -149,11 +152,13 @@ export const buildTelegramMessageContext = async ({
149152
const resolvedThreadId = threadSpec.scope === "forum" ? threadSpec.id : undefined;
150153
const replyThreadId = threadSpec.id;
151154
const dmThreadId = threadSpec.scope === "dm" ? threadSpec.id : undefined;
152-
const topicNameCachePath = sessionRuntime?.resolveStorePath
153-
? resolveTopicNameCachePath(
154-
sessionRuntime.resolveStorePath(cfg.session?.store, { agentId: account.accountId }),
155-
)
156-
: undefined;
155+
const topicNameCachePath = resolveTopicNameCachePath(
156+
await resolveTelegramMessageContextStorePath({
157+
cfg,
158+
agentId: account.accountId,
159+
sessionRuntime,
160+
}),
161+
);
157162
let topicName: string | undefined;
158163
if (isForum && resolvedThreadId != null) {
159164
const ftCreated = msg.forum_topic_created;

0 commit comments

Comments
 (0)