






















@@ -3702,13 +3702,11 @@ describe("dispatchReplyFromConfig", () => {
37023702});
3703370337043704expect(replyResolver).toHaveBeenCalledTimes(1);
3705-expect(diagnosticMocks.logMessageProcessed).toHaveBeenCalledWith(
3706-expect.objectContaining({
3707-channel: "whatsapp",
3708-outcome: "skipped",
3709-reason: "duplicate",
3710-}),
3711-);
3705+const skippedEvent = diagnosticMocks.logMessageProcessed.mock.calls
3706+.map(([event]) => event as { channel?: unknown; outcome?: unknown; reason?: unknown })
3707+.find((event) => event.outcome === "skipped");
3708+expect(skippedEvent?.channel).toBe("whatsapp");
3709+expect(skippedEvent?.reason).toBe("duplicate");
37123710});
3713371137143712it("releases inbound dedupe when dispatch fails before completion", async () => {
@@ -3750,13 +3748,11 @@ describe("dispatchReplyFromConfig", () => {
37503748});
3751374937523750expect(replyResolver).toHaveBeenCalledTimes(2);
3753-expect(diagnosticMocks.logMessageProcessed).toHaveBeenCalledWith(
3754-expect.objectContaining({
3755-channel: "whatsapp",
3756-outcome: "error",
3757-error: "Error: dispatch failed",
3758-}),
3759-);
3751+const errorEvent = diagnosticMocks.logMessageProcessed.mock.calls
3752+.map(([event]) => event as { channel?: unknown; error?: unknown; outcome?: unknown })
3753+.find((event) => event.outcome === "error");
3754+expect(errorEvent?.channel).toBe("whatsapp");
3755+expect(errorEvent?.error).toBe("Error: dispatch failed");
37603756});
3761375737623758it("poisons inbound dedupe when dispatch fails after a block reply", async () => {
@@ -3914,7 +3910,7 @@ describe("dispatchReplyFromConfig", () => {
39143910await dispatchReplyFromConfig({ ctx, cfg: emptyConfig, dispatcher, replyResolver });
39153911const finalCalls = (dispatcher.sendFinalReply as ReturnType<typeof vi.fn>).mock.calls;
39163912expect(finalCalls).toHaveLength(1);
3917-expect(finalCalls[0][0]).toMatchObject({ text: "The answer is 42" });
3913+expect((finalCalls[0]?.[0] as ReplyPayload | undefined)?.text).toBe("The answer is 42");
39183914});
3919391539203916it("suppresses isReasoning payloads from block replies (generic dispatch path)", async () => {
@@ -3973,15 +3969,14 @@ describe("dispatchReplyFromConfig", () => {
39733969expect(blockReplySentTexts).toEqual(["Intro ", " visible"]);
39743970expect(blockReplySentTexts.join("")).not.toContain("[[tts");
39753971expect(blockReplySentTexts.join("")).not.toContain("hidden");
3976-expect(ttsMocks.maybeApplyTtsToPayload).toHaveBeenCalledWith(
3977-expect.objectContaining({
3978-kind: "final",
3979-payload: { text: "Intro [[tts:text]]hidden[[/tts:text]] visible" },
3980-}),
3981-);
3982-expect(dispatcher.sendFinalReply).toHaveBeenCalledWith(
3983-expect.objectContaining({ mediaUrl: "https://example.com/tts-synth.opus" }),
3984-);
3972+const ttsCall = ttsMocks.maybeApplyTtsToPayload.mock.calls
3973+.map(([call]) => call as { kind?: unknown; payload?: ReplyPayload })
3974+.find((call) => call.kind === "final");
3975+expect(ttsCall?.kind).toBe("final");
3976+expect(ttsCall?.payload).toEqual({ text: "Intro [[tts:text]]hidden[[/tts:text]] visible" });
3977+const finalPayload = (dispatcher.sendFinalReply as ReturnType<typeof vi.fn>).mock
3978+.calls[0]?.[0] as ReplyPayload | undefined;
3979+expect(finalPayload?.mediaUrl).toBe("https://example.com/tts-synth.opus");
39853980});
3986398139873982it("forwards generated-media block replies in WhatsApp group sessions", async () => {
@@ -4080,7 +4075,7 @@ describe("dispatchReplyFromConfig", () => {
4080407540814076expect(onBlockReplyQueued).toHaveBeenCalledWith(
40824077{ text: "Alpha" },
4083-expect.objectContaining({ assistantMessageIndex: 7 }),
4078+{ assistantMessageIndex: 7 },
40844079);
40854080});
40864081});
@@ -4160,32 +4155,36 @@ describe("before_dispatch hook", () => {
4160415541614156const result = await dispatchReplyFromConfig({ ctx, cfg: emptyConfig, dispatcher });
416241574163-expect(hookMocks.runner.runBeforeDispatch).toHaveBeenCalledWith(
4164-expect.objectContaining({
4165-content: "command body",
4166-body: "agent body",
4167-channel: "telegram",
4168-senderId: "signal:user:alice",
4169-isGroup: true,
4170-timestamp: 123,
4171-}),
4172-expect.objectContaining({
4173-channelId: "telegram",
4174-senderId: "signal:user:alice",
4175-}),
4176-);
4158+const beforeDispatchCall = hookMocks.runner.runBeforeDispatch.mock.calls[0] as
4159+| [
4160+{
4161+body?: unknown;
4162+channel?: unknown;
4163+content?: unknown;
4164+isGroup?: unknown;
4165+senderId?: unknown;
4166+timestamp?: unknown;
4167+},
4168+{ channelId?: unknown; senderId?: unknown },
4169+]
4170+| undefined;
4171+expect(beforeDispatchCall?.[0]?.content).toBe("command body");
4172+expect(beforeDispatchCall?.[0]?.body).toBe("agent body");
4173+expect(beforeDispatchCall?.[0]?.channel).toBe("telegram");
4174+expect(beforeDispatchCall?.[0]?.senderId).toBe("signal:user:alice");
4175+expect(beforeDispatchCall?.[0]?.isGroup).toBe(true);
4176+expect(beforeDispatchCall?.[0]?.timestamp).toBe(123);
4177+expect(beforeDispatchCall?.[1]?.channelId).toBe("telegram");
4178+expect(beforeDispatchCall?.[1]?.senderId).toBe("signal:user:alice");
41774179expect(dispatcher.sendFinalReply).not.toHaveBeenCalled();
4178-expect(mocks.routeReply).toHaveBeenCalledWith(
4179-expect.objectContaining({
4180-channel: "telegram",
4181-to: "telegram:999",
4182-payload: expect.objectContaining({
4183-text: "Blocked",
4184-mediaUrl: "https://example.com/tts-synth.opus",
4185-audioAsVoice: true,
4186-}),
4187-}),
4188-);
4180+const routeCall = mocks.routeReply.mock.calls[0]?.[0] as
4181+| { channel?: unknown; payload?: ReplyPayload; to?: unknown }
4182+| undefined;
4183+expect(routeCall?.channel).toBe("telegram");
4184+expect(routeCall?.to).toBe("telegram:999");
4185+expect(routeCall?.payload?.text).toBe("Blocked");
4186+expect(routeCall?.payload?.mediaUrl).toBe("https://example.com/tts-synth.opus");
4187+expect(routeCall?.payload?.audioAsVoice).toBe(true);
41894188expect(result.queuedFinal).toBe(true);
41904189});
41914190@@ -4301,15 +4300,22 @@ describe("sendPolicy deny — suppress delivery, not processing (#53328)", () =>
43014300replyResolver: async () => ({ text: "agent reply" }),
43024301});
430343024304-expect(hookMocks.runner.runReplyDispatch).toHaveBeenCalledWith(
4305-expect.objectContaining({
4306-isTailDispatch: true,
4307-sendPolicy: "deny",
4308-suppressUserDelivery: true,
4309-suppressReplyLifecycle: true,
4310-}),
4311-expect.any(Object),
4303+const tailDispatchCall = hookMocks.runner.runReplyDispatch.mock.calls.find(
4304+([event]) => (event as { isTailDispatch?: boolean }).isTailDispatch === true,
43124305);
4306+const tailDispatchEvent = tailDispatchCall?.[0] as
4307+| {
4308+isTailDispatch?: unknown;
4309+sendPolicy?: unknown;
4310+suppressReplyLifecycle?: unknown;
4311+suppressUserDelivery?: unknown;
4312+}
4313+| undefined;
4314+expect(tailDispatchEvent?.isTailDispatch).toBe(true);
4315+expect(tailDispatchEvent?.sendPolicy).toBe("deny");
4316+expect(tailDispatchEvent?.suppressUserDelivery).toBe(true);
4317+expect(tailDispatchEvent?.suppressReplyLifecycle).toBe(true);
4318+expect(tailDispatchCall?.[1]).toBeDefined();
43134319});
4314432043154321it("suppresses final reply delivery when sendPolicy is deny", async () => {
@@ -4633,15 +4639,24 @@ describe("sendPolicy deny — suppress delivery, not processing (#53328)", () =>
46334639}
46344640expect(callback).not.toHaveBeenCalled();
46354641}
4636-expect(hookMocks.runner.runReplyDispatch).toHaveBeenCalledWith(
4637-expect.objectContaining({
4638-suppressUserDelivery: true,
4639-suppressReplyLifecycle: false,
4640-sourceReplyDeliveryMode: "message_tool_only",
4641-sendPolicy: "allow",
4642-}),
4643-expect.any(Object),
4642+const replyDispatchCall = hookMocks.runner.runReplyDispatch.mock.calls.find(
4643+([event]) =>
4644+(event as { sourceReplyDeliveryMode?: unknown }).sourceReplyDeliveryMode ===
4645+"message_tool_only",
46444646);
4647+const replyDispatchEvent = replyDispatchCall?.[0] as
4648+| {
4649+sendPolicy?: unknown;
4650+sourceReplyDeliveryMode?: unknown;
4651+suppressReplyLifecycle?: unknown;
4652+suppressUserDelivery?: unknown;
4653+}
4654+| undefined;
4655+expect(replyDispatchEvent?.suppressUserDelivery).toBe(true);
4656+expect(replyDispatchEvent?.suppressReplyLifecycle).toBe(false);
4657+expect(replyDispatchEvent?.sourceReplyDeliveryMode).toBe("message_tool_only");
4658+expect(replyDispatchEvent?.sendPolicy).toBe("allow");
4659+expect(replyDispatchCall?.[1]).toBeDefined();
46454660});
4646466146474662it("preserves hook-blocked metadata when source delivery is message-tool-only", async () => {
@@ -4817,8 +4832,8 @@ describe("sendPolicy deny — suppress delivery, not processing (#53328)", () =>
4817483248184833expect(replyResolver).toHaveBeenCalledTimes(1);
48194834expect(result.queuedFinal).toBe(true);
4820-expect(dispatcher.sendFinalReply).toHaveBeenCalledWith(
4821-expect.objectContaining({ text: "visible direct reply" }),
4835+expect((dispatcher.sendFinalReply as ReturnType<typeof vi.fn>).mock.calls[0]?.[0]?.text).toBe(
4836+"visible direct reply",
48224837);
48234838});
48244839@@ -4879,8 +4894,8 @@ describe("sendPolicy deny — suppress delivery, not processing (#53328)", () =>
4879489448804895expect(replyResolver).toHaveBeenCalledTimes(1);
48814896expect(result.queuedFinal).toBe(true);
4882-expect(dispatcher.sendFinalReply).toHaveBeenCalledWith(
4883-expect.objectContaining({ text: "visible fallback" }),
4897+expect((dispatcher.sendFinalReply as ReturnType<typeof vi.fn>).mock.calls[0]?.[0]?.text).toBe(
4898+"visible fallback",
48844899);
48854900});
48864901@@ -4915,8 +4930,8 @@ describe("sendPolicy deny — suppress delivery, not processing (#53328)", () =>
4915493049164931expect(replyResolver).toHaveBeenCalledTimes(1);
49174932expect(result.queuedFinal).toBe(true);
4918-expect(dispatcher.sendFinalReply).toHaveBeenCalledWith(
4919-expect.objectContaining({ text: "group policy fallback" }),
4933+expect((dispatcher.sendFinalReply as ReturnType<typeof vi.fn>).mock.calls[0]?.[0]?.text).toBe(
4934+"group policy fallback",
49204935);
49214936});
49224937@@ -4943,8 +4958,8 @@ describe("sendPolicy deny — suppress delivery, not processing (#53328)", () =>
4943495849444959expect(replyResolver).toHaveBeenCalledTimes(1);
49454960expect(result.queuedFinal).toBe(true);
4946-expect(dispatcher.sendFinalReply).toHaveBeenCalledWith(
4947-expect.objectContaining({ text: "requested fallback" }),
4961+expect((dispatcher.sendFinalReply as ReturnType<typeof vi.fn>).mock.calls[0]?.[0]?.text).toBe(
4962+"requested fallback",
49484963);
49494964});
49504965@@ -4972,8 +4987,8 @@ describe("sendPolicy deny — suppress delivery, not processing (#53328)", () =>
4972498749734988expect(replyResolver).toHaveBeenCalledTimes(1);
49744989expect(result.queuedFinal).toBe(true);
4975-expect(dispatcher.sendFinalReply).toHaveBeenCalledWith(
4976-expect.objectContaining({ text: "status reply" }),
4990+expect((dispatcher.sendFinalReply as ReturnType<typeof vi.fn>).mock.calls[0]?.[0]?.text).toBe(
4991+"status reply",
49774992);
49784993});
49794994@@ -4998,8 +5013,8 @@ describe("sendPolicy deny — suppress delivery, not processing (#53328)", () =>
4998501349995014expect(replyResolver).toHaveBeenCalledTimes(1);
50005015expect(result.queuedFinal).toBe(true);
5001-expect(dispatcher.sendFinalReply).toHaveBeenCalledWith(
5002-expect.objectContaining({ text: "final reply" }),
5016+expect((dispatcher.sendFinalReply as ReturnType<typeof vi.fn>).mock.calls[0]?.[0]?.text).toBe(
5017+"final reply",
50035018);
50045019});
50055020});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。