fix(telegram): align directive reply prompt timestamps

This commit is contained in:
momothemage
2026-07-06 14:18:29 +08:00
parent 8a3b4c2549
commit 5c4cc7245e
3 changed files with 42 additions and 2 deletions

View File

@@ -1884,6 +1884,38 @@ describe("dispatchTelegramMessage draft streaming", () => {
expect(deliverReplies).not.toHaveBeenCalled();
});
it("marks directive-tagged durable finals with the transcript prompt-context timestamp", async () => {
const transcriptTimestamp = Date.now() + 1_000;
const context = createContext();
context.ctxPayload.SessionKey = "agent:default:telegram:direct:123";
mockDefaultSessionEntry();
readLatestAssistantTextByIdentity.mockResolvedValue({
text: "[[reply_to_current]]Final answer",
timestamp: transcriptTimestamp,
});
deliverInboundReplyWithMessageSendContext.mockResolvedValue({
status: "handled_visible",
delivery: {
messageIds: ["2001"],
visibleReplySent: true,
},
});
dispatchReplyWithBufferedBlockDispatcher.mockImplementation(async ({ dispatcherOptions }) => {
await dispatcherOptions.deliver({ text: "Final answer" }, { kind: "final" });
return { queuedFinal: true };
});
await dispatchWithContext({ context, streamMode: "off" });
const outbound = expectRecordFields(mockCallArg(deliverInboundReplyWithMessageSendContext), {
payload: expect.objectContaining({ text: "Final answer" }),
});
expectRecordFields(expectRecordFields(outbound.payload, {}).channelData, {
telegram: { promptContextTimestampMs: transcriptTimestamp },
});
expect(deliverReplies).not.toHaveBeenCalled();
});
it("keeps the Telegram edit cap for non-block previews regardless of chunk config", async () => {
const draftStream = createDraftStream();
createTelegramDraftStream.mockReturnValue(draftStream);

View File

@@ -54,6 +54,7 @@ import {
appendAssistantMirrorMessageByIdentity,
readLatestAssistantTextByIdentity,
} from "openclaw/plugin-sdk/session-transcript-runtime";
import { stripInlineDirectiveTagsForDelivery } from "openclaw/plugin-sdk/text-chunking";
import { resolveTelegramConfigReasoningDefault } from "./agent-config.js";
import { withTelegramApiErrorLogging } from "./api-logging.js";
import type { TelegramBotDeps } from "./bot-deps.js";
@@ -1580,9 +1581,14 @@ export const dispatchTelegramMessage = async ({
};
const resolveCurrentTurnTranscriptFinalText = async (): Promise<string | undefined> =>
(await resolveCurrentTurnTranscriptFinal())?.text;
const normalizePromptContextTimestampText = (text: string): string =>
stripInlineDirectiveTagsForDelivery(text).text.trim();
const resolvePromptContextTimestampMs = async (text: string): Promise<number | undefined> => {
const final = await resolveCurrentTurnTranscriptFinal();
if (final?.text.trim() !== text.trim()) {
if (
!final ||
normalizePromptContextTimestampText(final.text) !== normalizePromptContextTimestampText(text)
) {
return undefined;
}
return final.timestamp;

View File

@@ -2461,6 +2461,7 @@ describe("createTelegramBot", () => {
const senderId = 202;
const visibleReply = "Yep - I'm here now.";
const replyTimestampMs = 1_778_474_700_000;
const telegramReplyDate = Math.floor((replyTimestampMs + 5_000) / 1000);
await writeDirectTelegramTranscriptContext({
cfg: config,
@@ -2482,9 +2483,10 @@ describe("createTelegramBot", () => {
from: { id: senderId, is_bot: false, first_name: "Kesava" },
reply_to_message: {
chat: { id: chatId, type: "private" },
date: Math.floor(replyTimestampMs / 1000),
date: telegramReplyDate,
from: { id: 999, is_bot: true, first_name: "OpenClaw" },
message_id: 736,
openclaw_prompt_context_timestamp_ms: replyTimestampMs,
text: visibleReply,
},
},