fix(telegram): persist topic cache via default runtime

This commit is contained in:
Ayaan Zaidi
2026-04-14 00:12:58 +05:30
parent 4f92b1fbb0
commit c91d3d4537
3 changed files with 78 additions and 8 deletions

View File

@@ -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", () => {

View File

@@ -76,6 +76,17 @@ async function loadTelegramMessageContextSessionRuntime(
};
}
export async function resolveTelegramMessageContextStorePath(params: {
cfg: OpenClawConfig;
agentId: string;
sessionRuntime?: TelegramMessageContextSessionRuntimeOverrides;
}): Promise<string> {
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({

View File

@@ -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;