diff --git a/extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.test.ts b/extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.test.ts index 73a72405671..cf33bc207ff 100644 --- a/extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.test.ts +++ b/extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.test.ts @@ -311,19 +311,7 @@ describe("telegram live qa runtime", () => { }); it("includes mention gating in the Telegram live scenario catalog", () => { - expect( - __testing - .findScenario([ - "telegram-help-command", - "telegram-commands-command", - "telegram-tools-compact-command", - "telegram-whoami-command", - "telegram-context-command", - "telegram-mentioned-message-reply", - "telegram-mention-gating", - ]) - .map((scenario) => scenario.id), - ).toEqual([ + const scenarios = __testing.findScenario([ "telegram-help-command", "telegram-commands-command", "telegram-tools-compact-command", @@ -332,6 +320,20 @@ describe("telegram live qa runtime", () => { "telegram-mentioned-message-reply", "telegram-mention-gating", ]); + expect(scenarios.map((scenario) => scenario.id)).toEqual([ + "telegram-help-command", + "telegram-commands-command", + "telegram-tools-compact-command", + "telegram-whoami-command", + "telegram-context-command", + "telegram-mentioned-message-reply", + "telegram-mention-gating", + ]); + expect( + scenarios + .find((scenario) => scenario.id === "telegram-mentioned-message-reply") + ?.buildRun("sut_bot").replyToLatestSutMessage, + ).toBe(true); }); it("tracks Telegram live coverage against the shared transport contract", () => { diff --git a/extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts b/extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts index 8ff5843ab6d..18a3fcc1e70 100644 --- a/extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts +++ b/extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts @@ -56,6 +56,7 @@ type TelegramQaScenarioRun = { input: string; expectedTextIncludes?: string[]; matchText?: string; + replyToLatestSutMessage?: boolean; }; type TelegramQaScenarioDefinition = LiveTransportScenarioDefinition & { @@ -276,6 +277,7 @@ const TELEGRAM_QA_SCENARIOS: TelegramQaScenarioDefinition[] = [ allowAnySutReply: true, expectReply: true, input: `@${sutUsername} Telegram QA mention routing check. Reply with a short acknowledgement.`, + replyToLatestSutMessage: true, }), }, { @@ -613,11 +615,24 @@ async function flushTelegramUpdates(token: string) { throw new Error("timed out after 15000ms draining Telegram updates"); } -async function sendGroupMessage(token: string, groupId: string, text: string) { +async function sendGroupMessage( + token: string, + groupId: string, + text: string, + opts: { replyToMessageId?: number } = {}, +) { return await callTelegramApi(token, "sendMessage", { chat_id: groupId, text, disable_notification: true, + ...(opts.replyToMessageId !== undefined + ? { + reply_parameters: { + message_id: opts.replyToMessageId, + allow_sending_without_reply: true, + }, + } + : {}), }); } @@ -1228,6 +1243,7 @@ export async function runTelegramQaLive(params: { try { await waitForTelegramChannelRunning(gatewayHarness.gateway, sutAccountId); assertLeaseHealthy(); + let latestSutMessageId: number | undefined; try { writeTelegramQaProgress(progressEnabled, "canary start"); const canaryTiming = await runCanary({ @@ -1238,6 +1254,7 @@ export async function runTelegramQaLive(params: { timeoutMs: resolveTelegramQaCanaryTimeoutMs(), observedMessages, }); + latestSutMessageId = canaryTiming.responseMessageId; scenarioResults.push({ id: "telegram-canary", title: "Telegram canary", @@ -1291,6 +1308,9 @@ export async function runTelegramQaLive(params: { runtimeEnv.driverToken, runtimeEnv.groupId, scenarioRun.input, + scenarioRun.replyToLatestSutMessage + ? { replyToMessageId: latestSutMessageId } + : undefined, ); const requestStartedAt = new Date(requestStartedAtMs).toISOString(); const matched = await waitForObservedMessage({ @@ -1333,6 +1353,7 @@ export async function runTelegramQaLive(params: { responseMessageId: redactPublicMetadata ? undefined : matched.message.messageId, } satisfies TelegramQaScenarioResult; scenarioResults.push(result); + latestSutMessageId = matched.message.messageId; writeTelegramQaProgress( progressEnabled, `scenario pass ${scenarioIndexLabel}: ${scenarioIdForLog}`,