



















@@ -2401,18 +2401,11 @@ describe("dispatchReplyFromConfig", () => {
2401240124022402await dispatchReplyFromConfig({ ctx, cfg, dispatcher, replyResolver });
240324032404-expect(sessionBindingMocks.resolveByConversation).toHaveBeenCalledWith(
2405-expect.objectContaining({
2406-channel: "discord",
2407-accountId: "work",
2408-conversationId: "thread-1",
2409-}),
2410-);
2411-expect(dispatcher.sendToolResult).toHaveBeenCalledWith(
2412-expect.objectContaining({
2413-text: expect.stringContaining("not currently loaded"),
2414-}),
2415-);
2404+const bindingLookup = sessionBindingMocks.resolveByConversation.mock.calls[0]?.[0];
2405+expect(bindingLookup?.channel).toBe("discord");
2406+expect(bindingLookup?.accountId).toBe("work");
2407+expect(bindingLookup?.conversationId).toBe("thread-1");
2408+expect(firstToolResultPayload(dispatcher)?.text).toContain("not currently loaded");
24162409expect(replyResolver).toHaveBeenCalled();
24172410});
24182411@@ -2493,21 +2486,18 @@ describe("dispatchReplyFromConfig", () => {
24932486conversationId: "C123",
24942487});
24952488expect(sessionBindingMocks.touch).toHaveBeenCalledWith("binding-acp-current");
2496-expect(runtime.ensureSession).toHaveBeenCalledWith(
2497-expect.objectContaining({
2498-sessionKey: boundSessionKey,
2499-agent: "opencode",
2500-}),
2501-);
2502-expect(runtime.runTurn).toHaveBeenCalledWith(
2503-expect.objectContaining({
2504-text: "continue",
2505-}),
2506-);
2489+const ensureSessionOptions = runtime.ensureSession.mock.calls[0]?.[0] as
2490+| { agent?: unknown; sessionKey?: unknown }
2491+| undefined;
2492+expect(ensureSessionOptions?.sessionKey).toBe(boundSessionKey);
2493+expect(ensureSessionOptions?.agent).toBe("opencode");
2494+const runTurnOptions = runtime.runTurn.mock.calls[0]?.[0] as { text?: unknown } | undefined;
2495+expect(runTurnOptions?.text).toBe("continue");
25072496expect(replyResolver).not.toHaveBeenCalled();
2508-expect(dispatcher.sendBlockReply).toHaveBeenCalledWith(
2509-expect.objectContaining({ text: "Bound ACP reply" }),
2510-);
2497+const blockPayload = (dispatcher.sendBlockReply as Mock).mock.calls[0]?.[0] as
2498+| ReplyPayload
2499+| undefined;
2500+expect(blockPayload?.text).toBe("Bound ACP reply");
25112501});
2512250225132503it("coalesces tiny ACP token deltas into normal Discord text spacing", async () => {
@@ -2567,9 +2557,10 @@ describe("dispatchReplyFromConfig", () => {
25672557}
25682558}
25692559expect(blockTexts).toEqual(["What do you want to work on?"]);
2570-expect(dispatcher.sendFinalReply).toHaveBeenCalledWith(
2571-expect.objectContaining({ text: "What do you want to work on?" }),
2572-);
2560+const finalPayload = (dispatcher.sendFinalReply as Mock).mock.calls[0]?.[0] as
2561+| ReplyPayload
2562+| undefined;
2563+expect(finalPayload?.text).toBe("What do you want to work on?");
25732564});
2574256525752566it("generates final-mode TTS audio after ACP block streaming completes", async () => {
@@ -2648,19 +2639,16 @@ describe("dispatchReplyFromConfig", () => {
2648263926492640await dispatchReplyFromConfig({ ctx, cfg: emptyConfig, dispatcher, replyResolver });
265026412651-expect(replyMediaPathMocks.createReplyMediaPathNormalizer).toHaveBeenCalledWith(
2652-expect.objectContaining({
2653-messageProvider: "feishu",
2654-}),
2655-);
2656-expect(dispatcher.sendFinalReply).toHaveBeenCalledWith(
2657-expect.objectContaining({
2658-mediaUrl: "/tmp/openclaw-media/normalized-tts.ogg",
2659-mediaUrls: ["/tmp/openclaw-media/normalized-tts.ogg"],
2660-audioAsVoice: true,
2661-spokenText: "Hello from block streaming.",
2662-}),
2663-);
2642+const normalizerOptions = replyMediaPathMocks.createReplyMediaPathNormalizer.mock
2643+.calls[0]?.[0] as { messageProvider?: unknown } | undefined;
2644+expect(normalizerOptions?.messageProvider).toBe("feishu");
2645+const finalPayload = (dispatcher.sendFinalReply as Mock).mock.calls[0]?.[0] as
2646+| ReplyPayload
2647+| undefined;
2648+expect(finalPayload?.mediaUrl).toBe("/tmp/openclaw-media/normalized-tts.ogg");
2649+expect(finalPayload?.mediaUrls).toStrictEqual(["/tmp/openclaw-media/normalized-tts.ogg"]);
2650+expect(finalPayload?.audioAsVoice).toBe(true);
2651+expect(finalPayload?.spokenText).toBe("Hello from block streaming.");
26642652});
2665265326662654it("closes oneshot ACP sessions after the turn completes", async () => {
@@ -2702,11 +2690,8 @@ describe("dispatchReplyFromConfig", () => {
2702269027032691await dispatchReplyFromConfig({ ctx, cfg, dispatcher });
270426922705-expect(runtime.close).toHaveBeenCalledWith(
2706-expect.objectContaining({
2707-reason: "oneshot-complete",
2708-}),
2709-);
2693+const closeOptions = runtime.close.mock.calls[0]?.[0] as { reason?: unknown } | undefined;
2694+expect(closeOptions?.reason).toBe("oneshot-complete");
27102695});
2711269627122697it("deduplicates inbound messages by MessageSid and origin", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。