diff --git a/extensions/telegram/src/bot.create-telegram-bot.test.ts b/extensions/telegram/src/bot.create-telegram-bot.test.ts index d0df14e7cf6..7fbab89cdab 100644 --- a/extensions/telegram/src/bot.create-telegram-bot.test.ts +++ b/extensions/telegram/src/bot.create-telegram-bot.test.ts @@ -59,6 +59,7 @@ const TELEGRAM_TEST_TIMINGS = { mediaGroupFlushMs: 20, textFragmentGapMs: 30, } as const; +const EMPTY_REPLY_COUNTS = { block: 0, final: 0, tool: 0 } as const; describe("createTelegramBot", () => { beforeAll(() => { @@ -388,7 +389,7 @@ describe("createTelegramBot", () => { dispatchReplyWithBufferedBlockDispatcher.mockImplementationOnce( async ({ dispatcherOptions }) => { await dispatcherOptions.typingCallbacks?.onReplyStart?.(); - return { queuedFinal: false, counts: {} }; + return { queuedFinal: false, counts: { ...EMPTY_REPLY_COUNTS } }; }, ); createTelegramBot({ token: "tok" }); @@ -1463,7 +1464,7 @@ describe("createTelegramBot", () => { dispatchReplyWithBufferedBlockDispatcher.mockImplementationOnce(async (params) => { dispatchCall = params as typeof dispatchCall; await params.dispatcherOptions.typingCallbacks?.onReplyStart?.(); - return { queuedFinal: false, counts: {} }; + return { queuedFinal: false, counts: { ...EMPTY_REPLY_COUNTS } }; }); loadConfig.mockReturnValue({ channels: { @@ -1479,6 +1480,9 @@ describe("createTelegramBot", () => { const payload = dispatchCall?.ctx; if (testCase.assertTopicMetadata) { + if (!payload) { + throw new Error("Expected forum dispatch payload"); + } expect(payload.SessionKey).toContain("telegram:group:-1001234567890:topic:99"); expect(payload.From).toBe("telegram:group:-1001234567890:topic:99"); expect(payload.MessageThreadId).toBe(99); @@ -1790,7 +1794,7 @@ describe("createTelegramBot", () => { | undefined; dispatchReplyWithBufferedBlockDispatcher.mockImplementationOnce(async (params) => { dispatchCall = params as typeof dispatchCall; - return { queuedFinal: false, counts: {} }; + return { queuedFinal: false, counts: { ...EMPTY_REPLY_COUNTS } }; }); loadConfig.mockReturnValue({ channels: { @@ -1819,6 +1823,9 @@ describe("createTelegramBot", () => { await handler(makeForumGroupMessageCtx({ threadId: 99 })); const payload = dispatchCall?.ctx; + if (!payload) { + throw new Error("Expected topic dispatch payload"); + } expect(payload.GroupSystemPrompt).toBe("Group prompt\n\nTopic prompt"); expect(dispatchCall?.replyOptions?.skillFilter).toEqual([]); }); diff --git a/extensions/telegram/src/bot.media.e2e-harness.ts b/extensions/telegram/src/bot.media.e2e-harness.ts index 3dbd8634ab1..56af46fc304 100644 --- a/extensions/telegram/src/bot.media.e2e-harness.ts +++ b/extensions/telegram/src/bot.media.e2e-harness.ts @@ -1,7 +1,14 @@ import path from "node:path"; +import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; import { MediaFetchError } from "openclaw/plugin-sdk/media-runtime"; -import { resetInboundDedupe } from "openclaw/plugin-sdk/reply-runtime"; +import { + resetInboundDedupe, + type GetReplyOptions, + type MsgContext, + type ReplyPayload, +} from "openclaw/plugin-sdk/reply-runtime"; import { beforeEach, vi, type Mock } from "vitest"; +import type { TelegramBotDeps } from "./bot-deps.js"; export const useSpy: Mock = vi.fn(); export const middlewareUseSpy: Mock = vi.fn(); @@ -97,7 +104,11 @@ const apiStub: ApiStub = { setMyCommands: vi.fn(async () => undefined), }; -export const telegramBotRuntimeForTest = { +export const telegramBotRuntimeForTest: { + Bot: new (token: string) => unknown; + sequentialize: () => unknown; + apiThrottler: () => unknown; +} = { Bot: class { api = apiStub; use = middlewareUseSpy; @@ -111,7 +122,13 @@ export const telegramBotRuntimeForTest = { apiThrottler: () => throttlerSpy(), }; -const mediaHarnessReplySpy = vi.hoisted(() => vi.fn(async () => undefined)); +type MediaHarnessReplyFn = ( + ctx: MsgContext, + opts?: GetReplyOptions, + configOverride?: OpenClawConfig, +) => Promise; + +const mediaHarnessReplySpy = vi.hoisted(() => vi.fn(async () => undefined)); type DispatchReplyWithBufferedBlockDispatcherFn = typeof import("openclaw/plugin-sdk/reply-runtime").dispatchReplyWithBufferedBlockDispatcher; type DispatchReplyHarnessParams = Parameters[0]; @@ -121,8 +138,11 @@ let actualDispatchReplyWithBufferedBlockDispatcherPromise: | undefined; async function getActualDispatchReplyWithBufferedBlockDispatcher() { - actualDispatchReplyWithBufferedBlockDispatcherPromise ??= - import("../../../src/auto-reply/reply/provider-dispatcher.js").then( + actualDispatchReplyWithBufferedBlockDispatcherPromise ??= vi + .importActual( + "openclaw/plugin-sdk/reply-runtime", + ) + .then( (module) => module.dispatchReplyWithBufferedBlockDispatcher as DispatchReplyWithBufferedBlockDispatcherFn, ); @@ -136,9 +156,9 @@ async function dispatchReplyWithBufferedBlockDispatcherViaActual( await getActualDispatchReplyWithBufferedBlockDispatcher(); return await actualDispatchReplyWithBufferedBlockDispatcher({ ...params, - replyResolver: async (ctx, _cfg, opts) => { + replyResolver: async (ctx, opts, configOverride) => { await opts?.onReplyStart?.(); - return await mediaHarnessReplySpy(ctx, opts); + return await mediaHarnessReplySpy(ctx, opts, configOverride as OpenClawConfig | undefined); }, }); } @@ -148,7 +168,7 @@ const mediaHarnessDispatchReplyWithBufferedBlockDispatcher = vi.hoisted(() => dispatchReplyWithBufferedBlockDispatcherViaActual, ), ); -export const telegramBotDepsForTest = { +export const telegramBotDepsForTest: TelegramBotDeps = { loadConfig: () => ({ channels: { telegram: { dmPolicy: "open", allowFrom: ["*"] } }, }),