refactor: share setup account config patch helper

This commit is contained in:
Peter Steinberger
2026-03-07 19:53:31 +00:00
parent 2ee8b807f8
commit b0ac284dae
11 changed files with 176 additions and 150 deletions

View File

@@ -256,18 +256,6 @@ export const bluebubblesPlugin: ChannelPlugin<ResolvedBlueBubblesAccount> = {
channelKey: "bluebubbles", channelKey: "bluebubbles",
}) })
: namedConfig; : namedConfig;
if (accountId === DEFAULT_ACCOUNT_ID) {
return applyBlueBubblesConnectionConfig({
cfg: next,
accountId,
patch: {
serverUrl: input.httpUrl,
password: input.password,
webhookPath: input.webhookPath,
},
onlyDefinedFields: true,
});
}
return applyBlueBubblesConnectionConfig({ return applyBlueBubblesConnectionConfig({
cfg: next, cfg: next,
accountId, accountId,

View File

@@ -1,5 +1,6 @@
import { import {
applyAccountNameToChannelSection, applyAccountNameToChannelSection,
applySetupAccountConfigPatch,
buildChannelConfigSchema, buildChannelConfigSchema,
DEFAULT_ACCOUNT_ID, DEFAULT_ACCOUNT_ID,
deleteAccountFromConfigSection, deleteAccountFromConfigSection,
@@ -345,37 +346,12 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
...(webhookPath ? { webhookPath } : {}), ...(webhookPath ? { webhookPath } : {}),
...(webhookUrl ? { webhookUrl } : {}), ...(webhookUrl ? { webhookUrl } : {}),
}; };
if (accountId === DEFAULT_ACCOUNT_ID) { return applySetupAccountConfigPatch({
return { cfg: next,
...next, channelKey: "googlechat",
channels: { accountId,
...next.channels, patch: configPatch,
googlechat: { });
...next.channels?.["googlechat"],
enabled: true,
...configPatch,
},
},
} as OpenClawConfig;
}
return {
...next,
channels: {
...next.channels,
googlechat: {
...next.channels?.["googlechat"],
enabled: true,
accounts: {
...next.channels?.["googlechat"]?.accounts,
[accountId]: {
...next.channels?.["googlechat"]?.accounts?.[accountId],
enabled: true,
...configPatch,
},
},
},
},
} as OpenClawConfig;
}, },
}, },
outbound: { outbound: {

View File

@@ -1,5 +1,6 @@
import { import {
applyAccountNameToChannelSection, applyAccountNameToChannelSection,
applySetupAccountConfigPatch,
buildChannelConfigSchema, buildChannelConfigSchema,
DEFAULT_ACCOUNT_ID, DEFAULT_ACCOUNT_ID,
deleteAccountFromConfigSection, deleteAccountFromConfigSection,
@@ -449,43 +450,18 @@ export const mattermostPlugin: ChannelPlugin<ResolvedMattermostAccount> = {
channelKey: "mattermost", channelKey: "mattermost",
}) })
: namedConfig; : namedConfig;
if (accountId === DEFAULT_ACCOUNT_ID) { const patch = input.useEnv
return { ? {}
...next, : {
channels: { ...(token ? { botToken: token } : {}),
...next.channels, ...(baseUrl ? { baseUrl } : {}),
mattermost: { };
...next.channels?.mattermost, return applySetupAccountConfigPatch({
enabled: true, cfg: next,
...(input.useEnv channelKey: "mattermost",
? {} accountId,
: { patch,
...(token ? { botToken: token } : {}), });
...(baseUrl ? { baseUrl } : {}),
}),
},
},
};
}
return {
...next,
channels: {
...next.channels,
mattermost: {
...next.channels?.mattermost,
enabled: true,
accounts: {
...next.channels?.mattermost?.accounts,
[accountId]: {
...next.channels?.mattermost?.accounts?.[accountId],
enabled: true,
...(token ? { botToken: token } : {}),
...(baseUrl ? { baseUrl } : {}),
},
},
},
},
};
}, },
}, },
gateway: { gateway: {

View File

@@ -6,6 +6,7 @@ import type {
} from "openclaw/plugin-sdk/zalo"; } from "openclaw/plugin-sdk/zalo";
import { import {
applyAccountNameToChannelSection, applyAccountNameToChannelSection,
applySetupAccountConfigPatch,
buildBaseAccountStatusSnapshot, buildBaseAccountStatusSnapshot,
buildChannelConfigSchema, buildChannelConfigSchema,
buildTokenChannelStatusSummary, buildTokenChannelStatusSummary,
@@ -243,47 +244,19 @@ export const zaloPlugin: ChannelPlugin<ResolvedZaloAccount> = {
channelKey: "zalo", channelKey: "zalo",
}) })
: namedConfig; : namedConfig;
if (accountId === DEFAULT_ACCOUNT_ID) { const patch = input.useEnv
return { ? {}
...next, : input.tokenFile
channels: { ? { tokenFile: input.tokenFile }
...next.channels, : input.token
zalo: { ? { botToken: input.token }
...next.channels?.zalo, : {};
enabled: true, return applySetupAccountConfigPatch({
...(input.useEnv cfg: next,
? {} channelKey: "zalo",
: input.tokenFile accountId,
? { tokenFile: input.tokenFile } patch,
: input.token });
? { botToken: input.token }
: {}),
},
},
} as OpenClawConfig;
}
return {
...next,
channels: {
...next.channels,
zalo: {
...next.channels?.zalo,
enabled: true,
accounts: {
...next.channels?.zalo?.accounts,
[accountId]: {
...next.channels?.zalo?.accounts?.[accountId],
enabled: true,
...(input.tokenFile
? { tokenFile: input.tokenFile }
: input.token
? { botToken: input.token }
: {}),
},
},
},
},
} as OpenClawConfig;
}, },
}, },
pairing: { pairing: {

View File

@@ -10,6 +10,7 @@ import type {
} from "openclaw/plugin-sdk/zalouser"; } from "openclaw/plugin-sdk/zalouser";
import { import {
applyAccountNameToChannelSection, applyAccountNameToChannelSection,
applySetupAccountConfigPatch,
buildChannelSendResult, buildChannelSendResult,
buildBaseAccountStatusSnapshot, buildBaseAccountStatusSnapshot,
buildChannelConfigSchema, buildChannelConfigSchema,
@@ -329,35 +330,12 @@ export const zalouserPlugin: ChannelPlugin<ResolvedZalouserAccount> = {
channelKey: "zalouser", channelKey: "zalouser",
}) })
: namedConfig; : namedConfig;
if (accountId === DEFAULT_ACCOUNT_ID) { return applySetupAccountConfigPatch({
return { cfg: next,
...next, channelKey: "zalouser",
channels: { accountId,
...next.channels, patch: {},
zalouser: { });
...next.channels?.zalouser,
enabled: true,
},
},
} as OpenClawConfig;
}
return {
...next,
channels: {
...next.channels,
zalouser: {
...next.channels?.zalouser,
enabled: true,
accounts: {
...next.channels?.zalouser?.accounts,
[accountId]: {
...next.channels?.zalouser?.accounts?.[accountId],
enabled: true,
},
},
},
},
} as OpenClawConfig;
}, },
}, },
messaging: { messaging: {

View File

@@ -0,0 +1,81 @@
import { describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../../config/config.js";
import { DEFAULT_ACCOUNT_ID } from "../../routing/session-key.js";
import { applySetupAccountConfigPatch } from "./setup-helpers.js";
function asConfig(value: unknown): OpenClawConfig {
return value as OpenClawConfig;
}
describe("applySetupAccountConfigPatch", () => {
it("patches top-level config for default account and enables channel", () => {
const next = applySetupAccountConfigPatch({
cfg: asConfig({
channels: {
zalo: {
webhookPath: "/old",
enabled: false,
},
},
}),
channelKey: "zalo",
accountId: DEFAULT_ACCOUNT_ID,
patch: { webhookPath: "/new", botToken: "tok" },
});
expect(next.channels?.zalo).toMatchObject({
enabled: true,
webhookPath: "/new",
botToken: "tok",
});
});
it("patches named account config and enables both channel and account", () => {
const next = applySetupAccountConfigPatch({
cfg: asConfig({
channels: {
zalo: {
enabled: false,
accounts: {
work: { botToken: "old", enabled: false },
},
},
},
}),
channelKey: "zalo",
accountId: "work",
patch: { botToken: "new" },
});
expect(next.channels?.zalo).toMatchObject({
enabled: true,
accounts: {
work: { enabled: true, botToken: "new" },
},
});
});
it("normalizes account id and preserves other accounts", () => {
const next = applySetupAccountConfigPatch({
cfg: asConfig({
channels: {
zalo: {
accounts: {
personal: { botToken: "personal-token" },
},
},
},
}),
channelKey: "zalo",
accountId: "Work Team",
patch: { botToken: "work-token" },
});
expect(next.channels?.zalo).toMatchObject({
accounts: {
personal: { botToken: "personal-token" },
"work-team": { enabled: true, botToken: "work-token" },
},
});
});
});

View File

@@ -120,6 +120,56 @@ export function migrateBaseNameToDefaultAccount(params: {
} as OpenClawConfig; } as OpenClawConfig;
} }
export function applySetupAccountConfigPatch(params: {
cfg: OpenClawConfig;
channelKey: string;
accountId: string;
patch: Record<string, unknown>;
}): OpenClawConfig {
const accountId = normalizeAccountId(params.accountId);
const channels = params.cfg.channels as Record<string, unknown> | undefined;
const channelConfig = channels?.[params.channelKey];
const base =
typeof channelConfig === "object" && channelConfig
? (channelConfig as Record<string, unknown> & {
accounts?: Record<string, Record<string, unknown>>;
})
: undefined;
if (accountId === DEFAULT_ACCOUNT_ID) {
return {
...params.cfg,
channels: {
...params.cfg.channels,
[params.channelKey]: {
...base,
enabled: true,
...params.patch,
},
},
} as OpenClawConfig;
}
const accounts = base?.accounts ?? {};
return {
...params.cfg,
channels: {
...params.cfg.channels,
[params.channelKey]: {
...base,
enabled: true,
accounts: {
...accounts,
[accountId]: {
...accounts[accountId],
enabled: true,
...params.patch,
},
},
},
},
} as OpenClawConfig;
}
type ChannelSectionRecord = Record<string, unknown> & { type ChannelSectionRecord = Record<string, unknown> & {
accounts?: Record<string, Record<string, unknown>>; accounts?: Record<string, Record<string, unknown>>;
}; };

View File

@@ -30,6 +30,7 @@ export {
export { PAIRING_APPROVED_MESSAGE } from "../channels/plugins/pairing-message.js"; export { PAIRING_APPROVED_MESSAGE } from "../channels/plugins/pairing-message.js";
export { export {
applyAccountNameToChannelSection, applyAccountNameToChannelSection,
applySetupAccountConfigPatch,
migrateBaseNameToDefaultAccount, migrateBaseNameToDefaultAccount,
} from "../channels/plugins/setup-helpers.js"; } from "../channels/plugins/setup-helpers.js";
export { createAccountListHelpers } from "../channels/plugins/account-helpers.js"; export { createAccountListHelpers } from "../channels/plugins/account-helpers.js";

View File

@@ -35,6 +35,7 @@ export {
} from "../channels/plugins/onboarding/helpers.js"; } from "../channels/plugins/onboarding/helpers.js";
export { export {
applyAccountNameToChannelSection, applyAccountNameToChannelSection,
applySetupAccountConfigPatch,
migrateBaseNameToDefaultAccount, migrateBaseNameToDefaultAccount,
} from "../channels/plugins/setup-helpers.js"; } from "../channels/plugins/setup-helpers.js";
export { createAccountListHelpers } from "../channels/plugins/account-helpers.js"; export { createAccountListHelpers } from "../channels/plugins/account-helpers.js";

View File

@@ -23,6 +23,7 @@ export {
export { PAIRING_APPROVED_MESSAGE } from "../channels/plugins/pairing-message.js"; export { PAIRING_APPROVED_MESSAGE } from "../channels/plugins/pairing-message.js";
export { export {
applyAccountNameToChannelSection, applyAccountNameToChannelSection,
applySetupAccountConfigPatch,
migrateBaseNameToDefaultAccount, migrateBaseNameToDefaultAccount,
} from "../channels/plugins/setup-helpers.js"; } from "../channels/plugins/setup-helpers.js";
export { createAccountListHelpers } from "../channels/plugins/account-helpers.js"; export { createAccountListHelpers } from "../channels/plugins/account-helpers.js";

View File

@@ -23,6 +23,7 @@ export {
} from "../channels/plugins/onboarding/helpers.js"; } from "../channels/plugins/onboarding/helpers.js";
export { export {
applyAccountNameToChannelSection, applyAccountNameToChannelSection,
applySetupAccountConfigPatch,
migrateBaseNameToDefaultAccount, migrateBaseNameToDefaultAccount,
} from "../channels/plugins/setup-helpers.js"; } from "../channels/plugins/setup-helpers.js";
export { createAccountListHelpers } from "../channels/plugins/account-helpers.js"; export { createAccountListHelpers } from "../channels/plugins/account-helpers.js";