feat: show status reaction during context compaction (#35474)

Merged via squash.

Prepared head SHA: 145a7b7c4e
Co-authored-by: Cypherm <28184436+Cypherm@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
This commit is contained in:
Cypherm
2026-03-13 12:06:15 +08:00
committed by GitHub
parent 4e872521f0
commit 61d219cb39
15 changed files with 169 additions and 10 deletions

View File

@@ -2182,4 +2182,41 @@ describe("dispatchTelegramMessage draft streaming", () => {
);
expect(finalTextSentViaDeliverReplies).toBe(true);
});
it("shows compacting reaction during auto-compaction and resumes thinking", async () => {
const statusReactionController = {
setThinking: vi.fn(async () => {}),
setCompacting: vi.fn(async () => {}),
setTool: vi.fn(async () => {}),
setDone: vi.fn(async () => {}),
setError: vi.fn(async () => {}),
setQueued: vi.fn(async () => {}),
cancelPending: vi.fn(() => {}),
clear: vi.fn(async () => {}),
restoreInitial: vi.fn(async () => {}),
};
dispatchReplyWithBufferedBlockDispatcher.mockImplementation(async ({ replyOptions }) => {
await replyOptions?.onCompactionStart?.();
await replyOptions?.onCompactionEnd?.();
return { queuedFinal: true };
});
deliverReplies.mockResolvedValue({ delivered: true });
await dispatchWithContext({
context: createContext({
statusReactionController: statusReactionController as never,
}),
streamMode: "off",
});
expect(statusReactionController.setCompacting).toHaveBeenCalledTimes(1);
expect(statusReactionController.cancelPending).toHaveBeenCalledTimes(1);
expect(statusReactionController.setThinking).toHaveBeenCalledTimes(2);
expect(statusReactionController.setCompacting.mock.invocationCallOrder[0]).toBeLessThan(
statusReactionController.cancelPending.mock.invocationCallOrder[0],
);
expect(statusReactionController.cancelPending.mock.invocationCallOrder[0]).toBeLessThan(
statusReactionController.setThinking.mock.invocationCallOrder[1],
);
});
});

View File

@@ -713,6 +713,15 @@ export const dispatchTelegramMessage = async ({
await statusReactionController.setTool(payload.name);
}
: undefined,
onCompactionStart: statusReactionController
? () => statusReactionController.setCompacting()
: undefined,
onCompactionEnd: statusReactionController
? async () => {
statusReactionController.cancelPending();
await statusReactionController.setThinking();
}
: undefined,
onModelSelected,
},
}));

View File

@@ -90,6 +90,7 @@ export const TELEGRAM_STATUS_REACTION_VARIANTS: Record<StatusReactionEmojiKey, s
error: ["😱", "😨", "🤯"],
stallSoft: ["🥱", "😴", "🤔"],
stallHard: ["😨", "😱", "⚡"],
compacting: ["✍", "🤔", "🤯"],
};
const STATUS_REACTION_EMOJI_KEYS: StatusReactionEmojiKey[] = [
@@ -102,6 +103,7 @@ const STATUS_REACTION_EMOJI_KEYS: StatusReactionEmojiKey[] = [
"error",
"stallSoft",
"stallHard",
"compacting",
];
function normalizeEmoji(value: string | undefined): string | undefined {
@@ -129,6 +131,7 @@ export function resolveTelegramStatusReactionEmojis(params: {
error: normalizeEmoji(overrides?.error) ?? DEFAULT_EMOJIS.error,
stallSoft: normalizeEmoji(overrides?.stallSoft) ?? DEFAULT_EMOJIS.stallSoft,
stallHard: normalizeEmoji(overrides?.stallHard) ?? DEFAULT_EMOJIS.stallHard,
compacting: normalizeEmoji(overrides?.compacting) ?? DEFAULT_EMOJIS.compacting,
};
}