diff --git a/src/infra/outbound/agent-delivery.test.ts b/src/infra/outbound/agent-delivery.test.ts index 96278e9c3da..abb3bb67d16 100644 --- a/src/infra/outbound/agent-delivery.test.ts +++ b/src/infra/outbound/agent-delivery.test.ts @@ -2,21 +2,79 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; const mocks = vi.hoisted(() => ({ resolveOutboundTarget: vi.fn(() => ({ ok: true as const, to: "+1999" })), + resolveSessionDeliveryTarget: vi.fn( + (params: { + entry?: { + deliveryContext?: { + channel?: string; + to?: string; + accountId?: string; + threadId?: string | number; + }; + lastChannel?: string; + lastTo?: string; + lastAccountId?: string; + lastThreadId?: string | number; + }; + requestedChannel?: string; + explicitTo?: string; + explicitThreadId?: string | number; + turnSourceChannel?: string; + turnSourceTo?: string; + turnSourceAccountId?: string; + turnSourceThreadId?: string | number; + }) => { + const sessionContext = params.entry?.deliveryContext ?? { + channel: params.entry?.lastChannel, + to: params.entry?.lastTo, + accountId: params.entry?.lastAccountId, + threadId: params.entry?.lastThreadId, + }; + const lastChannel = params.turnSourceChannel ?? sessionContext.channel; + const lastTo = params.turnSourceChannel ? params.turnSourceTo : sessionContext.to; + const lastAccountId = params.turnSourceChannel + ? params.turnSourceAccountId + : sessionContext.accountId; + const lastThreadId = params.turnSourceChannel + ? params.turnSourceThreadId + : sessionContext.threadId; + const channel = + params.requestedChannel === "last" || params.requestedChannel == null + ? lastChannel + : params.requestedChannel; + const mode = params.explicitTo ? "explicit" : "implicit"; + const resolvedTo = + params.explicitTo ?? (channel && channel === lastChannel ? lastTo : undefined); + + return { + channel, + to: resolvedTo, + accountId: channel && channel === lastChannel ? lastAccountId : undefined, + threadId: + params.explicitThreadId ?? + (channel && channel === lastChannel ? lastThreadId : undefined), + threadIdExplicit: params.explicitThreadId != null, + mode, + lastChannel, + lastTo, + lastAccountId, + lastThreadId, + }; + }, + ), })); -vi.mock("./targets.js", async () => { - const actual = await vi.importActual("./targets.js"); - return { - ...actual, - resolveOutboundTarget: mocks.resolveOutboundTarget, - }; -}); +vi.mock("./targets.js", () => ({ + resolveOutboundTarget: mocks.resolveOutboundTarget, + resolveSessionDeliveryTarget: mocks.resolveSessionDeliveryTarget, +})); import type { OpenClawConfig } from "../../config/config.js"; import { resolveAgentDeliveryPlan, resolveAgentOutboundTarget } from "./agent-delivery.js"; beforeEach(() => { mocks.resolveOutboundTarget.mockClear(); + mocks.resolveSessionDeliveryTarget.mockClear(); }); describe("agent delivery helpers", () => { diff --git a/src/infra/outbound/targets.test.ts b/src/infra/outbound/targets.test.ts index 11d22f33a27..8c9f3dde6ae 100644 --- a/src/infra/outbound/targets.test.ts +++ b/src/infra/outbound/targets.test.ts @@ -1,8 +1,20 @@ -import { beforeEach, describe, expect, it } from "vitest"; +import { beforeEach, describe, expect, it, vi } from "vitest"; import type { ChannelOutboundAdapter } from "../../channels/plugins/types.js"; import type { OpenClawConfig } from "../../config/config.js"; import type { SessionEntry } from "../../config/sessions/types.js"; import { setActivePluginRegistry } from "../../plugins/runtime.js"; + +vi.mock("./channel-resolution.js", async () => { + const { getActivePluginRegistry } = await import("../../plugins/runtime.js"); + + return { + normalizeDeliverableOutboundChannel: (raw?: string | null) => + typeof raw === "string" && raw.trim() ? raw.trim().toLowerCase() : undefined, + resolveOutboundChannelPlugin: ({ channel }: { channel: string }) => + getActivePluginRegistry()?.channels.find((entry) => entry?.plugin?.id === channel)?.plugin, + }; +}); + import { resolveHeartbeatDeliveryTarget, resolveOutboundTarget,