Files
openclaw/extensions/whatsapp/src/account-config.ts
Peter Steinberger 4a05a087a1 refactor(config): retire flat streaming keys from the last six channel schemas via doctor migration (#105709)
* refactor(config): retire flat streaming keys from the last six channel schemas

signal, irc, nextcloud-talk, whatsapp, googlechat, and mattermost now accept
only the nested streaming.{chunkMode,block.enabled,block.coalesce} shape
(mattermost also drops scalar/boolean streaming); flat spellings migrate via
each channel's defineChannelAliasMigration doctor contract with root seeding
for their wholesale-replace account merges.

* feat(channels): warn once per key when the deprecated flat streaming fallback is used

Bundled schemas now reject the flat delivery keys, so the streaming.ts
fallback only serves external SDK plugin configs; emit a once-per-process
per-key subsystem warning and pin the removal plan to the next release train.

* chore(config): regenerate bundled channel config metadata for nested-only streaming

* docs: describe nested-only channel streaming config and the SDK flat-key deprecation window

* fix(whatsapp): seed migrated named-account streaming from the accounts.default layer

WhatsApp resolution layers accounts.default shared config between root and
named accounts, so doctor-materialized account streaming objects now inherit
default-account settings over root ones; mattermost schema test moves to the
nested-only shape with explicit rejection coverage; scope flat-key deprecation
notes to the pending Matrix/Feishu migrations.

* fix(whatsapp): resolve the default account case-insensitively when seeding migrated streaming

* chore(plugin-sdk): repin API baseline for nested-only channel streaming types
2026-07-12 15:27:28 -07:00

70 lines
2.3 KiB
TypeScript

// Whatsapp helper module supports account config behavior.
import {
DEFAULT_ACCOUNT_ID,
mergeAccountConfig,
resolveAccountEntry,
resolveMergedAccountConfig,
type OpenClawConfig,
} from "openclaw/plugin-sdk/account-core";
import type { WhatsAppAccountConfig } from "./account-types.js";
function resolveWhatsAppDefaultAccountSharedConfig(
cfg: OpenClawConfig,
): Partial<WhatsAppAccountConfig> | undefined {
const defaultAccount = resolveAccountEntry(cfg.channels?.whatsapp?.accounts, DEFAULT_ACCOUNT_ID);
if (!defaultAccount) {
return undefined;
}
const {
enabled: _ignoredEnabled,
name: _ignoredName,
authDir: _ignoredAuthDir,
selfChatMode: _ignoredSelfChatMode,
...sharedDefaults
} = defaultAccount;
return sharedDefaults;
}
function resolveWhatsAppAccountConfigForTest(
cfg: OpenClawConfig,
accountId: string,
): WhatsAppAccountConfig | undefined {
return resolveAccountEntry(cfg.channels?.whatsapp?.accounts, accountId);
}
function resolveMergedNamedWhatsAppAccountConfig(params: {
cfg: OpenClawConfig;
accountId: string;
}): WhatsAppAccountConfig {
const rootCfg = params.cfg.channels?.whatsapp;
const accountConfig = resolveWhatsAppAccountConfigForTest(params.cfg, params.accountId);
return {
...mergeAccountConfig<WhatsAppAccountConfig>({
channelConfig: rootCfg as WhatsAppAccountConfig | undefined,
accountConfig: undefined,
omitKeys: ["defaultAccount"],
}),
...resolveWhatsAppDefaultAccountSharedConfig(params.cfg),
...accountConfig,
};
}
export function resolveMergedWhatsAppAccountConfig(params: {
cfg: OpenClawConfig;
accountId?: string | null;
}): WhatsAppAccountConfig & { accountId: string } {
const rootCfg = params.cfg.channels?.whatsapp;
const accountId = params.accountId?.trim() || rootCfg?.defaultAccount || DEFAULT_ACCOUNT_ID;
const base = resolveMergedAccountConfig<WhatsAppAccountConfig>({
channelConfig: rootCfg as WhatsAppAccountConfig | undefined,
accounts: rootCfg?.accounts as Record<string, Partial<WhatsAppAccountConfig>> | undefined,
accountId,
omitKeys: ["defaultAccount"],
});
const merged =
accountId === DEFAULT_ACCOUNT_ID
? base
: resolveMergedNamedWhatsAppAccountConfig({ cfg: params.cfg, accountId });
return { accountId, ...merged };
}