Fix outbound channel selection fast paths

This commit is contained in:
Tak Hoffman 2026-03-19 00:36:39 -05:00
parent 8b5206cc67
commit 080b574ad6
No known key found for this signature in database
4 changed files with 32 additions and 9 deletions

View File

@ -143,6 +143,24 @@ describe("resolveMessageChannelSelection", () => {
});
});
it("skips configured-channel scanning when includeConfigured is false", async () => {
const isConfigured = vi.fn(async () => true);
mocks.listChannelPlugins.mockReturnValue([makePlugin({ id: "whatsapp", isConfigured })]);
const selection = await resolveMessageChannelSelection({
cfg: {} as never,
channel: "telegram",
includeConfigured: false,
});
expect(selection).toEqual({
channel: "telegram",
configured: [],
source: "explicit",
});
expect(isConfigured).not.toHaveBeenCalled();
});
it("falls back to tool context channel when explicit channel is unknown", async () => {
const selection = await resolveMessageChannelSelection({
cfg: {} as never,

View File

@ -146,11 +146,15 @@ export async function resolveMessageChannelSelection(params: {
cfg: OpenClawConfig;
channel?: string | null;
fallbackChannel?: string | null;
includeConfigured?: boolean;
}): Promise<{
channel: MessageChannelId;
configured: MessageChannelId[];
source: MessageChannelSelectionSource;
}> {
const includeConfigured = params.includeConfigured !== false;
const resolveConfigured = async () =>
includeConfigured ? await listConfiguredMessageChannels(params.cfg) : [];
const normalized = normalizeMessageChannel(params.channel);
if (normalized) {
const availableExplicit = resolveAvailableKnownChannel({
@ -165,7 +169,7 @@ export async function resolveMessageChannelSelection(params: {
if (fallback) {
return {
channel: fallback,
configured: await listConfiguredMessageChannels(params.cfg),
configured: await resolveConfigured(),
source: "tool-context-fallback",
};
}
@ -176,7 +180,7 @@ export async function resolveMessageChannelSelection(params: {
}
return {
channel: availableExplicit,
configured: await listConfiguredMessageChannels(params.cfg),
configured: await resolveConfigured(),
source: "explicit",
};
}
@ -188,12 +192,12 @@ export async function resolveMessageChannelSelection(params: {
if (fallback) {
return {
channel: fallback,
configured: await listConfiguredMessageChannels(params.cfg),
configured: await resolveConfigured(),
source: "tool-context-fallback",
};
}
const configured = await listConfiguredMessageChannels(params.cfg);
const configured = await resolveConfigured();
if (configured.length === 1) {
return { channel: configured[0], configured, source: "single-configured" };
}

View File

@ -226,6 +226,7 @@ async function resolveChannel(
cfg,
channel: readStringParam(params, "channel"),
fallbackChannel: toolContext?.currentChannelProvider,
includeConfigured: false,
});
if (selection.source === "tool-context-fallback") {
params.channel = selection.channel;
@ -318,14 +319,13 @@ async function handleBroadcastAction(
throw new Error("Broadcast requires at least one target in --targets.");
}
const channelHint = readStringParam(params, "channel");
const configured = await listConfiguredMessageChannels(input.cfg);
if (configured.length === 0) {
throw new Error("Broadcast requires at least one configured channel.");
}
const targetChannels =
channelHint && channelHint.trim().toLowerCase() !== "all"
? [await resolveChannel(input.cfg, { channel: channelHint }, input.toolContext)]
: configured;
: await listConfiguredMessageChannels(input.cfg);
if (targetChannels.length === 0) {
throw new Error("Broadcast requires at least one configured channel.");
}
const results: Array<{
channel: ChannelId;
to: string;

View File

@ -136,6 +136,7 @@ async function resolveRequiredChannel(params: {
await resolveMessageChannelSelection({
cfg: params.cfg,
channel: params.channel,
includeConfigured: false,
})
).channel;
}