

























@@ -5,8 +5,14 @@ import type { Message } from "grammy/types";
55import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
66import { resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
77import { describe, expect, it } from "vitest";
8+import { resolveTelegramBotInfoCachePath } from "./bot-info-cache.js";
89import { resolveTelegramMessageCachePath } from "./message-cache.js";
910import { detectTelegramLegacyStateMigrations } from "./state-migrations.js";
11+import {
12+resolveTopicNameCacheNamespace,
13+resolveTopicNameCachePath,
14+resolveTopicNameCacheScope,
15+} from "./topic-name-cache.js";
10161117type PersistedCacheEntry = {
1218key: string;
@@ -31,6 +37,74 @@ function persistedCacheEntry(messageId: number, text: string): PersistedCacheEnt
3137}
32383339describe("telegram state migrations", () => {
40+it("detects legacy bot-info cache import", async () => {
41+const dir = await mkdtemp(path.join(os.tmpdir(), "openclaw-telegram-state-migration-"));
42+const env = { ...process.env, OPENCLAW_STATE_DIR: dir };
43+const persistedPath = resolveTelegramBotInfoCachePath("ops", env);
44+try {
45+await mkdir(path.dirname(persistedPath), { recursive: true });
46+await writeFile(
47+persistedPath,
48+JSON.stringify({
49+version: 1,
50+tokenFingerprint: "token:fingerprint",
51+fetchedAt: "2026-05-24T11:00:00.000Z",
52+botInfo: {
53+id: 123456,
54+is_bot: true,
55+first_name: "OpenClaw",
56+username: "openclaw_bot",
57+},
58+}),
59+);
60+61+const cfg = {
62+channels: {
63+telegram: {
64+accounts: {
65+ops: {
66+botToken: "123456:secret",
67+},
68+},
69+},
70+},
71+} as OpenClawConfig;
72+const plans = await detectTelegramLegacyStateMigrations({ cfg, env });
73+const botInfoPlan = plans.find(
74+(plan) =>
75+plan.kind === "plugin-state-import" && plan.label === "Telegram startup bot info cache",
76+);
77+78+expect(botInfoPlan).toMatchObject({
79+kind: "plugin-state-import",
80+sourcePath: persistedPath,
81+targetPath: "plugin state:telegram.bot-info-cache",
82+pluginId: "telegram",
83+namespace: "telegram.bot-info-cache",
84+scopeKey: "",
85+});
86+if (!botInfoPlan || botInfoPlan.kind !== "plugin-state-import") {
87+throw new Error("expected Telegram bot-info plugin-state import plan");
88+}
89+90+const entries = await botInfoPlan.readEntries();
91+expect(entries).toHaveLength(1);
92+expect(entries[0]).toMatchObject({
93+key: "ops",
94+value: {
95+tokenFingerprint: "token:fingerprint",
96+fetchedAt: "2026-05-24T11:00:00.000Z",
97+botInfo: {
98+id: 123456,
99+username: "openclaw_bot",
100+},
101+},
102+});
103+} finally {
104+await rm(dir, { recursive: true, force: true });
105+}
106+});
107+34108it("detects legacy message-cache import for the runtime sidecar path", async () => {
35109const dir = await mkdtemp(path.join(os.tmpdir(), "openclaw-telegram-state-migration-"));
36110const env = { ...process.env, OPENCLAW_STATE_DIR: dir };
@@ -73,4 +147,62 @@ describe("telegram state migrations", () => {
73147await rm(dir, { recursive: true, force: true });
74148}
75149});
150+151+it("detects legacy topic-name cache import for the runtime sidecar path", async () => {
152+const dir = await mkdtemp(path.join(os.tmpdir(), "openclaw-telegram-state-migration-"));
153+const env = { ...process.env, OPENCLAW_STATE_DIR: dir };
154+const storePath = resolveStorePath(undefined, { env });
155+const persistedPath = resolveTopicNameCachePath(storePath);
156+const namespace = resolveTopicNameCacheNamespace(resolveTopicNameCacheScope(storePath));
157+try {
158+await mkdir(path.dirname(persistedPath), { recursive: true });
159+await writeFile(
160+persistedPath,
161+JSON.stringify({
162+"7:42": {
163+name: "Deployments",
164+iconColor: 0x6fb9f0,
165+updatedAt: 1736380000,
166+},
167+}),
168+);
169+170+const cfg = {
171+agents: {
172+list: [{ id: "ops", default: true }],
173+},
174+} as OpenClawConfig;
175+const plans = await detectTelegramLegacyStateMigrations({ cfg, env });
176+const topicNamePlan = plans.find(
177+(plan) =>
178+plan.kind === "plugin-state-import" && plan.label === "Telegram forum topic-name cache",
179+);
180+181+expect(topicNamePlan).toMatchObject({
182+kind: "plugin-state-import",
183+sourcePath: persistedPath,
184+targetPath: `plugin state:${namespace}`,
185+pluginId: "telegram",
186+ namespace,
187+scopeKey: "",
188+});
189+if (!topicNamePlan || topicNamePlan.kind !== "plugin-state-import") {
190+throw new Error("expected Telegram topic-name plugin-state import plan");
191+}
192+193+const entries = await topicNamePlan.readEntries();
194+expect(entries).toStrictEqual([
195+{
196+key: "7:42",
197+value: {
198+name: "Deployments",
199+iconColor: 0x6fb9f0,
200+updatedAt: 1736380000,
201+},
202+},
203+]);
204+} finally {
205+await rm(dir, { recursive: true, force: true });
206+}
207+});
76208});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。