


























@@ -3267,13 +3267,14 @@ describe("handleFeishuMessage command authorization", () => {
3267326732683268await dispatchMessage({ cfg, event });
326932693270-const dispatcherOptions = mockCallArg<{ replyToMessageId?: string; rootId?: string }>(
3271-mockCreateFeishuReplyDispatcher,
3272-0,
3273-0,
3274-);
3270+const dispatcherOptions = mockCallArg<{
3271+replyToMessageId?: string;
3272+rootId?: string;
3273+typingTargetMessageId?: string;
3274+}>(mockCreateFeishuReplyDispatcher, 0, 0);
32753275expect(dispatcherOptions.replyToMessageId).toBe("om_root_topic");
32763276expect(dispatcherOptions.rootId).toBe("om_root_topic");
3277+expect(dispatcherOptions.typingTargetMessageId).toBe("om_child_message");
32773278});
3278327932793280it("replies to triggering message in normal group even when root_id is present (#32980)", async () => {
@@ -3345,13 +3346,14 @@ describe("handleFeishuMessage command authorization", () => {
3345334633463347await dispatchMessage({ cfg, event });
334733483348-const dispatcherOptions = mockCallArg<{ replyToMessageId?: string; rootId?: string }>(
3349-mockCreateFeishuReplyDispatcher,
3350-0,
3351-0,
3352-);
3349+const dispatcherOptions = mockCallArg<{
3350+replyToMessageId?: string;
3351+rootId?: string;
3352+typingTargetMessageId?: string;
3353+}>(mockCreateFeishuReplyDispatcher, 0, 0);
33533354expect(dispatcherOptions.replyToMessageId).toBe("om_topic_root");
33543355expect(dispatcherOptions.rootId).toBe("om_topic_root");
3356+expect(dispatcherOptions.typingTargetMessageId).toBe("om_topic_reply");
33553357});
3356335833573359it("replies to topic root in topic-sender group with root_id", async () => {
@@ -3384,13 +3386,48 @@ describe("handleFeishuMessage command authorization", () => {
3384338633853387await dispatchMessage({ cfg, event });
338633883387-const dispatcherOptions = mockCallArg<{ replyToMessageId?: string; rootId?: string }>(
3388-mockCreateFeishuReplyDispatcher,
3389-0,
3390-0,
3391-);
3389+const dispatcherOptions = mockCallArg<{
3390+replyToMessageId?: string;
3391+rootId?: string;
3392+typingTargetMessageId?: string;
3393+}>(mockCreateFeishuReplyDispatcher, 0, 0);
33923394expect(dispatcherOptions.replyToMessageId).toBe("om_topic_sender_root");
33933395expect(dispatcherOptions.rootId).toBe("om_topic_sender_root");
3396+expect(dispatcherOptions.typingTargetMessageId).toBe("om_topic_sender_reply");
3397+});
3398+3399+it("uses explicit synthetic typing targets without changing reply routing", async () => {
3400+mockShouldComputeCommandAuthorized.mockReturnValue(false);
3401+3402+const cfg: ClawdbotConfig = {
3403+channels: {
3404+feishu: {
3405+dmPolicy: "open",
3406+},
3407+},
3408+} as ClawdbotConfig;
3409+3410+const event: FeishuMessageEvent = {
3411+sender: { sender_id: { open_id: "ou-synthetic" } },
3412+message: {
3413+message_id: "synthetic-reaction-turn",
3414+typing_target_message_id: "om_reacted_message",
3415+reply_target_message_id: "om_reply_anchor",
3416+chat_id: "oc-synthetic-dm",
3417+chat_type: "p2p",
3418+message_type: "text",
3419+content: JSON.stringify({ text: "[reacted with THUMBSUP to message om_reply_anchor]" }),
3420+},
3421+};
3422+3423+await dispatchMessage({ cfg, event });
3424+3425+expect(mockCreateFeishuReplyDispatcher).toHaveBeenCalledWith(
3426+expect.objectContaining({
3427+replyToMessageId: "om_reply_anchor",
3428+typingTargetMessageId: "om_reacted_message",
3429+}),
3430+);
33943431});
3395343233963433it("keeps P2P replies inside a direct-message thread when Feishu supplies thread_id", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。