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 <chenglunhu@gmail.com>
This commit is contained in:
HCL 2026-03-03 08:54:07 +08:00 committed by Peter Steinberger
parent 90d8b40808
commit 586f057c24
2 changed files with 4 additions and 16 deletions

View File

@ -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 () => {

View File

@ -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];