From 5aa3574ffb2708ad715223c96cb60b2245282385 Mon Sep 17 00:00:00 2001 From: Gustavo Madeira Santana Date: Tue, 3 Mar 2026 03:24:02 -0500 Subject: [PATCH] refactor: share explicit-default warning text helpers --- src/commands/doctor-config-flow.ts | 13 +++++++++---- src/routing/default-account-warnings.ts | 17 +++++++++++++++++ src/telegram/accounts.ts | 4 ++-- 3 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 src/routing/default-account-warnings.ts diff --git a/src/commands/doctor-config-flow.ts b/src/commands/doctor-config-flow.ts index 69cbc764397..9e95575dcdc 100644 --- a/src/commands/doctor-config-flow.ts +++ b/src/commands/doctor-config-flow.ts @@ -26,6 +26,11 @@ import { normalizeTrustedSafeBinDirs, } from "../infra/exec-safe-bin-trust.js"; import { readChannelAllowFromStore } from "../pairing/pairing-store.js"; +import { + formatChannelAccountsDefaultPath, + formatSetExplicitDefaultInstruction, + formatSetExplicitDefaultToConfiguredInstruction, +} from "../routing/default-account-warnings.js"; import { DEFAULT_ACCOUNT_ID, normalizeAccountId, @@ -311,13 +316,13 @@ export function collectMissingDefaultAccountBindingWarnings(cfg: OpenClawConfig) } if (coveredAccountIds.size > 0) { warnings.push( - `- channels.${channelKey}: accounts.default is missing and account bindings only cover a subset of configured accounts. Uncovered accounts: ${uncoveredAccountIds.join(", ")}. Add bindings[].match.accountId for uncovered accounts (or "*"), or add channels.${channelKey}.accounts.default.`, + `- channels.${channelKey}: accounts.default is missing and account bindings only cover a subset of configured accounts. Uncovered accounts: ${uncoveredAccountIds.join(", ")}. Add bindings[].match.accountId for uncovered accounts (or "*"), or add ${formatChannelAccountsDefaultPath(channelKey)}.`, ); continue; } warnings.push( - `- channels.${channelKey}: accounts.default is missing and no valid account-scoped binding exists for configured accounts (${normalizedAccountIds.join(", ")}). Channel-only bindings (no accountId) match only default. Add bindings[].match.accountId for one of these accounts (or "*"), or add channels.${channelKey}.accounts.default.`, + `- channels.${channelKey}: accounts.default is missing and no valid account-scoped binding exists for configured accounts (${normalizedAccountIds.join(", ")}). Channel-only bindings (no accountId) match only default. Add bindings[].match.accountId for one of these accounts (or "*"), or add ${formatChannelAccountsDefaultPath(channelKey)}.`, ); } @@ -341,13 +346,13 @@ export function collectMissingExplicitDefaultAccountWarnings(cfg: OpenClawConfig continue; } warnings.push( - `- channels.${channelKey}: defaultAccount is set to "${preferredDefault}" but does not match configured accounts (${normalizedAccountIds.join(", ")}). Set channels.${channelKey}.defaultAccount to one of these accounts, or add channels.${channelKey}.accounts.default, to avoid fallback routing.`, + `- channels.${channelKey}: defaultAccount is set to "${preferredDefault}" but does not match configured accounts (${normalizedAccountIds.join(", ")}). ${formatSetExplicitDefaultToConfiguredInstruction({ channelKey })} to avoid fallback routing.`, ); continue; } warnings.push( - `- channels.${channelKey}: multiple accounts are configured but no explicit default is set. Add channels.${channelKey}.defaultAccount or channels.${channelKey}.accounts.default to avoid fallback routing.`, + `- channels.${channelKey}: multiple accounts are configured but no explicit default is set. ${formatSetExplicitDefaultInstruction(channelKey)} to avoid fallback routing.`, ); } diff --git a/src/routing/default-account-warnings.ts b/src/routing/default-account-warnings.ts new file mode 100644 index 00000000000..8c15aff4ed3 --- /dev/null +++ b/src/routing/default-account-warnings.ts @@ -0,0 +1,17 @@ +export function formatChannelDefaultAccountPath(channelKey: string): string { + return `channels.${channelKey}.defaultAccount`; +} + +export function formatChannelAccountsDefaultPath(channelKey: string): string { + return `channels.${channelKey}.accounts.default`; +} + +export function formatSetExplicitDefaultInstruction(channelKey: string): string { + return `Set ${formatChannelDefaultAccountPath(channelKey)} or add ${formatChannelAccountsDefaultPath(channelKey)}`; +} + +export function formatSetExplicitDefaultToConfiguredInstruction(params: { + channelKey: string; +}): string { + return `Set ${formatChannelDefaultAccountPath(params.channelKey)} to one of these accounts, or add ${formatChannelAccountsDefaultPath(params.channelKey)}`; +} diff --git a/src/telegram/accounts.ts b/src/telegram/accounts.ts index 5aad3154a24..81de42cd1f1 100644 --- a/src/telegram/accounts.ts +++ b/src/telegram/accounts.ts @@ -10,6 +10,7 @@ import { } from "../plugin-sdk/account-resolution.js"; import { resolveAccountEntry } from "../routing/account-lookup.js"; import { listBoundAccountIds, resolveDefaultAgentBoundAccountId } from "../routing/bindings.js"; +import { formatSetExplicitDefaultInstruction } from "../routing/default-account-warnings.js"; import { DEFAULT_ACCOUNT_ID, normalizeAccountId, @@ -90,8 +91,7 @@ export function resolveDefaultTelegramAccountId(cfg: OpenClawConfig): string { emittedMissingDefaultWarn = true; log.warn( `channels.telegram: accounts.default is missing; falling back to "${ids[0]}". ` + - "Set channels.telegram.defaultAccount or add an accounts.default entry " + - "to avoid routing surprises in multi-account setups.", + `${formatSetExplicitDefaultInstruction("telegram")} to avoid routing surprises in multi-account setups.`, ); } return ids[0] ?? DEFAULT_ACCOUNT_ID;