From 586f057c248a4f20ddaead6905e8a1cb223b676d Mon Sep 17 00:00:00 2001 From: HCL Date: Tue, 3 Mar 2026 08:54:07 +0800 Subject: [PATCH] fix(cron): let resolveOutboundTarget handle missing delivery target fallback The cron delivery path short-circuits with an error when `toCandidate` is falsy (line 151), before reaching `resolveOutboundTarget()` which provides the `plugin.config.resolveDefaultTo()` fallback. The direct send path in `targets.ts` already uses this fallback correctly. Remove the early `!toCandidate` exit so that `resolveOutboundTarget()` can attempt the plugin-provided default. Guard the WhatsApp allowFrom override against falsy `toCandidate` to maintain existing behavior when a target IS resolved. Fixes #32355 Signed-off-by: HCL --- src/cron/isolated-agent/delivery-target.test.ts | 4 +++- src/cron/isolated-agent/delivery-target.ts | 16 +--------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/cron/isolated-agent/delivery-target.test.ts b/src/cron/isolated-agent/delivery-target.test.ts index 14d02f0b380..0965c54d6b9 100644 --- a/src/cron/isolated-agent/delivery-target.test.ts +++ b/src/cron/isolated-agent/delivery-target.test.ts @@ -228,7 +228,9 @@ describe("resolveDeliveryTarget", () => { if (result.ok) { throw new Error("expected unresolved delivery target"); } - expect(result.error.message).toContain('No delivery target resolved for channel "telegram"'); + // resolveOutboundTarget provides the standard missing-target error when + // no explicit target, no session lastTo, and no plugin resolveDefaultTo. + expect(result.error.message).toContain("requires target"); }); it("returns an error when channel selection is ambiguous", async () => { diff --git a/src/cron/isolated-agent/delivery-target.ts b/src/cron/isolated-agent/delivery-target.ts index 3905ab695bd..1c27ed08b55 100644 --- a/src/cron/isolated-agent/delivery-target.ts +++ b/src/cron/isolated-agent/delivery-target.ts @@ -148,20 +148,6 @@ export async function resolveDeliveryTarget( }; } - if (!toCandidate) { - return { - ok: false, - channel, - to: undefined, - accountId, - threadId, - mode, - error: - channelResolutionError ?? - new Error(`No delivery target resolved for channel "${channel}". Set delivery.to.`), - }; - } - let allowFromOverride: string[] | undefined; if (channel === "whatsapp") { const resolvedAccountId = normalizeAccountId(accountId); @@ -177,7 +163,7 @@ export async function resolveDeliveryTarget( .filter((entry): entry is string => Boolean(entry)); allowFromOverride = [...new Set([...configuredAllowFrom, ...storeAllowFrom])]; - if (mode === "implicit" && allowFromOverride.length > 0) { + if (toCandidate && mode === "implicit" && allowFromOverride.length > 0) { const normalizedCurrentTarget = normalizeWhatsAppTarget(toCandidate); if (!normalizedCurrentTarget || !allowFromOverride.includes(normalizedCurrentTarget)) { toCandidate = allowFromOverride[0];