

























@@ -66,6 +66,8 @@ function createCardActionEvent(params: {
6666command: string;
6767chatId?: string;
6868chatType?: "group" | "p2p";
69+contextOpenMessageId?: string;
70+openMessageId?: string;
6971}) {
7072const openId = "ou_user1";
7173const chatId = params.chatId ?? "p2p:ou_user1";
@@ -77,6 +79,7 @@ function createCardActionEvent(params: {
7779union_id: "union_1",
7880},
7981token: params.token,
82+ ...(params.openMessageId ? { open_message_id: params.openMessageId } : {}),
8083action: {
8184tag: "button",
8285value: createFeishuCardInteractionEnvelope({
@@ -95,6 +98,7 @@ function createCardActionEvent(params: {
9598open_id: openId,
9699user_id: "user_1",
97100chat_id: chatId,
101+ ...(params.contextOpenMessageId ? { open_message_id: params.contextOpenMessageId } : {}),
98102},
99103};
100104}
@@ -253,6 +257,23 @@ describe("Feishu card-action lifecycle", () => {
253257expect(latestFinalizedContext().MessageSid).toBe("card-action-tok-card-v2-context");
254258});
255259260+it("prefers the original context message id over a temporary callback id", async () => {
261+const onCardAction = await setupLifecycleMonitor();
262+const event = createCardActionEvent({
263+token: "tok-card-original-target",
264+action: "feishu.quick_actions.help",
265+command: "/help",
266+openMessageId: "card-action-c-temporary",
267+contextOpenMessageId: "om_card_original",
268+});
269+270+await onCardAction(event);
271+272+expect(lastRuntime?.error).not.toHaveBeenCalled();
273+expect(dispatchReplyFromConfigMock).toHaveBeenCalledTimes(1);
274+expect(latestReplyDispatcherParams().replyToMessageId).toBe("om_card_original");
275+});
276+256277it("routes v2 callbacks with nested operator identity", async () => {
257278const onCardAction = await setupLifecycleMonitor();
258279const chatId = "p2p:ou_user1";
@@ -354,6 +375,22 @@ describe("Feishu card-action lifecycle", () => {
354375expect(latestFinalizedContext().MessageSid).toBe("card-action-tok-card-no-reply-target");
355376});
356377378+it("plain-sends card action replies when only a temporary callback id is available", async () => {
379+const onCardAction = await setupLifecycleMonitor();
380+const event = createCardActionEvent({
381+token: "tok-card-temporary-target",
382+action: "feishu.quick_actions.help",
383+command: "/help",
384+openMessageId: "card-action-c-temporary",
385+});
386+387+await onCardAction(event);
388+389+expect(lastRuntime?.error).not.toHaveBeenCalled();
390+expect(dispatchReplyFromConfigMock).toHaveBeenCalledTimes(1);
391+expect(latestReplyDispatcherParams().replyToMessageId).toBeUndefined();
392+});
393+357394it("does not duplicate delivery when retrying after a post-send failure", async () => {
358395const onCardAction = await setupLifecycleMonitor();
359396const event = createCardActionEvent({
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。