mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 05:41:24 +00:00
Feature/default messenger delivery target (openclaw#16985) thanks @KirillShchetinin
Verified: - pnpm build - pnpm check - pnpm test:macmini Co-authored-by: KirillShchetinin <13061871+KirillShchetinin@users.noreply.github.com> Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
59e58bf81c
commit
ee519086f6
@@ -1,5 +1,167 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveSessionDeliveryTarget } from "./targets.js";
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { telegramPlugin } from "../../../extensions/telegram/src/channel.js";
|
||||
import { whatsappPlugin } from "../../../extensions/whatsapp/src/channel.js";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
||||
import { createTestRegistry } from "../../test-utils/channel-plugins.js";
|
||||
import { resolveOutboundTarget, resolveSessionDeliveryTarget } from "./targets.js";
|
||||
|
||||
describe("resolveOutboundTarget", () => {
|
||||
beforeEach(() => {
|
||||
setActivePluginRegistry(
|
||||
createTestRegistry([
|
||||
{ pluginId: "whatsapp", plugin: whatsappPlugin, source: "test" },
|
||||
{ pluginId: "telegram", plugin: telegramPlugin, source: "test" },
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects whatsapp with empty target even when allowFrom configured", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
channels: { whatsapp: { allowFrom: ["+1555"] } },
|
||||
};
|
||||
const res = resolveOutboundTarget({
|
||||
channel: "whatsapp",
|
||||
to: "",
|
||||
cfg,
|
||||
mode: "explicit",
|
||||
});
|
||||
expect(res.ok).toBe(false);
|
||||
if (!res.ok) {
|
||||
expect(res.error.message).toContain("WhatsApp");
|
||||
}
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
name: "normalizes whatsapp target when provided",
|
||||
input: { channel: "whatsapp" as const, to: " (555) 123-4567 " },
|
||||
expected: { ok: true as const, to: "+5551234567" },
|
||||
},
|
||||
{
|
||||
name: "keeps whatsapp group targets",
|
||||
input: { channel: "whatsapp" as const, to: "120363401234567890@g.us" },
|
||||
expected: { ok: true as const, to: "120363401234567890@g.us" },
|
||||
},
|
||||
{
|
||||
name: "normalizes prefixed/uppercase whatsapp group targets",
|
||||
input: {
|
||||
channel: "whatsapp" as const,
|
||||
to: " WhatsApp:120363401234567890@G.US ",
|
||||
},
|
||||
expected: { ok: true as const, to: "120363401234567890@g.us" },
|
||||
},
|
||||
{
|
||||
name: "rejects whatsapp with empty target and allowFrom (no silent fallback)",
|
||||
input: { channel: "whatsapp" as const, to: "", allowFrom: ["+1555"] },
|
||||
expectedErrorIncludes: "WhatsApp",
|
||||
},
|
||||
{
|
||||
name: "rejects whatsapp with empty target and prefixed allowFrom (no silent fallback)",
|
||||
input: {
|
||||
channel: "whatsapp" as const,
|
||||
to: "",
|
||||
allowFrom: ["whatsapp:(555) 123-4567"],
|
||||
},
|
||||
expectedErrorIncludes: "WhatsApp",
|
||||
},
|
||||
{
|
||||
name: "rejects invalid whatsapp target",
|
||||
input: { channel: "whatsapp" as const, to: "wat" },
|
||||
expectedErrorIncludes: "WhatsApp",
|
||||
},
|
||||
{
|
||||
name: "rejects whatsapp without to when allowFrom missing",
|
||||
input: { channel: "whatsapp" as const, to: " " },
|
||||
expectedErrorIncludes: "WhatsApp",
|
||||
},
|
||||
{
|
||||
name: "rejects whatsapp allowFrom fallback when invalid",
|
||||
input: { channel: "whatsapp" as const, to: "", allowFrom: ["wat"] },
|
||||
expectedErrorIncludes: "WhatsApp",
|
||||
},
|
||||
])("$name", ({ input, expected, expectedErrorIncludes }) => {
|
||||
const res = resolveOutboundTarget(input);
|
||||
if (expected) {
|
||||
expect(res).toEqual(expected);
|
||||
return;
|
||||
}
|
||||
expect(res.ok).toBe(false);
|
||||
if (!res.ok) {
|
||||
expect(res.error.message).toContain(expectedErrorIncludes);
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects telegram with missing target", () => {
|
||||
const res = resolveOutboundTarget({ channel: "telegram", to: " " });
|
||||
expect(res.ok).toBe(false);
|
||||
if (!res.ok) {
|
||||
expect(res.error.message).toContain("Telegram");
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects webchat delivery", () => {
|
||||
const res = resolveOutboundTarget({ channel: "webchat", to: "x" });
|
||||
expect(res.ok).toBe(false);
|
||||
if (!res.ok) {
|
||||
expect(res.error.message).toContain("WebChat");
|
||||
}
|
||||
});
|
||||
|
||||
describe("defaultTo config fallback", () => {
|
||||
it("uses whatsapp defaultTo when no explicit target is provided", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
channels: { whatsapp: { defaultTo: "+15551234567", allowFrom: ["*"] } },
|
||||
};
|
||||
const res = resolveOutboundTarget({
|
||||
channel: "whatsapp",
|
||||
to: undefined,
|
||||
cfg,
|
||||
mode: "implicit",
|
||||
});
|
||||
expect(res).toEqual({ ok: true, to: "+15551234567" });
|
||||
});
|
||||
|
||||
it("uses telegram defaultTo when no explicit target is provided", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
channels: { telegram: { defaultTo: "123456789" } },
|
||||
};
|
||||
const res = resolveOutboundTarget({
|
||||
channel: "telegram",
|
||||
to: "",
|
||||
cfg,
|
||||
mode: "implicit",
|
||||
});
|
||||
expect(res).toEqual({ ok: true, to: "123456789" });
|
||||
});
|
||||
|
||||
it("explicit --reply-to overrides defaultTo", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
channels: { whatsapp: { defaultTo: "+15551234567", allowFrom: ["*"] } },
|
||||
};
|
||||
const res = resolveOutboundTarget({
|
||||
channel: "whatsapp",
|
||||
to: "+15559999999",
|
||||
cfg,
|
||||
mode: "explicit",
|
||||
});
|
||||
expect(res).toEqual({ ok: true, to: "+15559999999" });
|
||||
});
|
||||
|
||||
it("still errors when no defaultTo and no explicit target", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
channels: { whatsapp: { allowFrom: ["+1555"] } },
|
||||
};
|
||||
const res = resolveOutboundTarget({
|
||||
channel: "whatsapp",
|
||||
to: "",
|
||||
cfg,
|
||||
mode: "implicit",
|
||||
});
|
||||
expect(res.ok).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveSessionDeliveryTarget", () => {
|
||||
it("derives implicit delivery from the last route", () => {
|
||||
|
||||
@@ -169,20 +169,29 @@ export function resolveOutboundTarget(params: {
|
||||
})
|
||||
: undefined);
|
||||
|
||||
// Fall back to per-channel defaultTo when no explicit target is provided.
|
||||
const effectiveTo =
|
||||
params.to?.trim() ||
|
||||
(params.cfg && plugin.config.resolveDefaultTo
|
||||
? plugin.config.resolveDefaultTo({
|
||||
cfg: params.cfg,
|
||||
accountId: params.accountId ?? undefined,
|
||||
})
|
||||
: undefined);
|
||||
|
||||
const resolveTarget = plugin.outbound?.resolveTarget;
|
||||
if (resolveTarget) {
|
||||
return resolveTarget({
|
||||
cfg: params.cfg,
|
||||
to: params.to,
|
||||
to: effectiveTo,
|
||||
allowFrom,
|
||||
accountId: params.accountId ?? undefined,
|
||||
mode: params.mode ?? "explicit",
|
||||
});
|
||||
}
|
||||
|
||||
const trimmed = params.to?.trim();
|
||||
if (trimmed) {
|
||||
return { ok: true, to: trimmed };
|
||||
if (effectiveTo) {
|
||||
return { ok: true, to: effectiveTo };
|
||||
}
|
||||
const hint = plugin.messaging?.targetResolver?.hint;
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user