mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-02 10:30:22 +00:00
refactor: share account config merge helper
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
createAccountActionGate,
|
||||
createAccountListHelpers,
|
||||
mergeAccountConfig,
|
||||
} from "openclaw/plugin-sdk/account-helpers";
|
||||
import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
||||
import { resolveAccountEntry } from "openclaw/plugin-sdk/routing";
|
||||
@@ -31,11 +32,10 @@ export function mergeDiscordAccountConfig(
|
||||
cfg: OpenClawConfig,
|
||||
accountId: string,
|
||||
): DiscordAccountConfig {
|
||||
const { accounts: _ignored, ...base } = (cfg.channels?.discord ?? {}) as DiscordAccountConfig & {
|
||||
accounts?: unknown;
|
||||
};
|
||||
const account = resolveDiscordAccountConfig(cfg, accountId) ?? {};
|
||||
return { ...base, ...account };
|
||||
return mergeAccountConfig<DiscordAccountConfig>({
|
||||
channelConfig: cfg.channels?.discord as DiscordAccountConfig | undefined,
|
||||
accountConfig: resolveDiscordAccountConfig(cfg, accountId),
|
||||
});
|
||||
}
|
||||
|
||||
export function createDiscordActionGate(params: {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
createAccountListHelpers,
|
||||
mergeAccountConfig,
|
||||
normalizeAccountId,
|
||||
resolveAccountEntry,
|
||||
type OpenClawConfig,
|
||||
@@ -26,10 +27,10 @@ function resolveAccountConfig(
|
||||
}
|
||||
|
||||
function mergeIMessageAccountConfig(cfg: OpenClawConfig, accountId: string): IMessageAccountConfig {
|
||||
const { accounts: _ignored, ...base } = (cfg.channels?.imessage ??
|
||||
{}) as IMessageAccountConfig & { accounts?: unknown };
|
||||
const account = resolveAccountConfig(cfg, accountId) ?? {};
|
||||
return { ...base, ...account };
|
||||
return mergeAccountConfig<IMessageAccountConfig>({
|
||||
channelConfig: cfg.channels?.imessage as IMessageAccountConfig | undefined,
|
||||
accountConfig: resolveAccountConfig(cfg, accountId),
|
||||
});
|
||||
}
|
||||
|
||||
export function resolveIMessageAccount(params: {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
createAccountListHelpers,
|
||||
mergeAccountConfig,
|
||||
normalizeAccountId,
|
||||
resolveAccountEntry,
|
||||
type OpenClawConfig,
|
||||
@@ -27,11 +28,10 @@ function resolveAccountConfig(
|
||||
}
|
||||
|
||||
function mergeSignalAccountConfig(cfg: OpenClawConfig, accountId: string): SignalAccountConfig {
|
||||
const { accounts: _ignored, ...base } = (cfg.channels?.signal ?? {}) as SignalAccountConfig & {
|
||||
accounts?: unknown;
|
||||
};
|
||||
const account = resolveAccountConfig(cfg, accountId) ?? {};
|
||||
return { ...base, ...account };
|
||||
return mergeAccountConfig<SignalAccountConfig>({
|
||||
channelConfig: cfg.channels?.signal as SignalAccountConfig | undefined,
|
||||
accountConfig: resolveAccountConfig(cfg, accountId),
|
||||
});
|
||||
}
|
||||
|
||||
export function resolveSignalAccount(params: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
createAccountListHelpers,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
mergeAccountConfig,
|
||||
normalizeAccountId,
|
||||
normalizeChatType,
|
||||
resolveAccountEntry,
|
||||
@@ -40,11 +41,10 @@ export function mergeSlackAccountConfig(
|
||||
cfg: OpenClawConfig,
|
||||
accountId: string,
|
||||
): SlackAccountConfig {
|
||||
const { accounts: _ignored, ...base } = (cfg.channels?.slack ?? {}) as SlackAccountConfig & {
|
||||
accounts?: unknown;
|
||||
};
|
||||
const account = resolveAccountConfig(cfg, accountId) ?? {};
|
||||
return { ...base, ...account };
|
||||
return mergeAccountConfig<SlackAccountConfig>({
|
||||
channelConfig: cfg.channels?.slack as SlackAccountConfig | undefined,
|
||||
accountConfig: resolveAccountConfig(cfg, accountId),
|
||||
});
|
||||
}
|
||||
|
||||
export function resolveSlackAccount(params: {
|
||||
|
||||
48
extensions/zalo/src/accounts.test.ts
Normal file
48
extensions/zalo/src/accounts.test.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveZaloAccount } from "./accounts.js";
|
||||
|
||||
describe("resolveZaloAccount", () => {
|
||||
it("resolves account config when account key casing differs from normalized id", () => {
|
||||
const resolved = resolveZaloAccount({
|
||||
cfg: {
|
||||
channels: {
|
||||
zalo: {
|
||||
webhookUrl: "https://top.example.com",
|
||||
accounts: {
|
||||
Work: {
|
||||
name: "Work",
|
||||
webhookUrl: "https://work.example.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
accountId: "work",
|
||||
});
|
||||
|
||||
expect(resolved.accountId).toBe("work");
|
||||
expect(resolved.name).toBe("Work");
|
||||
expect(resolved.config.webhookUrl).toBe("https://work.example.com");
|
||||
});
|
||||
|
||||
it("falls back to top-level config for named accounts without overrides", () => {
|
||||
const resolved = resolveZaloAccount({
|
||||
cfg: {
|
||||
channels: {
|
||||
zalo: {
|
||||
enabled: true,
|
||||
webhookUrl: "https://top.example.com",
|
||||
accounts: {
|
||||
work: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
accountId: "work",
|
||||
});
|
||||
|
||||
expect(resolved.accountId).toBe("work");
|
||||
expect(resolved.enabled).toBe(true);
|
||||
expect(resolved.config.webhookUrl).toBe("https://top.example.com");
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createAccountListHelpers } from "openclaw/plugin-sdk/account-helpers";
|
||||
import { createAccountListHelpers, mergeAccountConfig } from "openclaw/plugin-sdk/account-helpers";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
||||
import { resolveAccountEntry } from "openclaw/plugin-sdk/routing";
|
||||
import type { OpenClawConfig } from "./runtime-api.js";
|
||||
import { resolveZaloToken } from "./token.js";
|
||||
import type { ResolvedZaloAccount, ZaloAccountConfig, ZaloConfig } from "./types.js";
|
||||
@@ -14,18 +15,20 @@ function resolveAccountConfig(
|
||||
cfg: OpenClawConfig,
|
||||
accountId: string,
|
||||
): ZaloAccountConfig | undefined {
|
||||
const accounts = (cfg.channels?.zalo as ZaloConfig | undefined)?.accounts;
|
||||
if (!accounts || typeof accounts !== "object") {
|
||||
return undefined;
|
||||
}
|
||||
return accounts[accountId] as ZaloAccountConfig | undefined;
|
||||
return resolveAccountEntry(
|
||||
(cfg.channels?.zalo as ZaloConfig | undefined)?.accounts as
|
||||
| Record<string, ZaloAccountConfig>
|
||||
| undefined,
|
||||
accountId,
|
||||
);
|
||||
}
|
||||
|
||||
function mergeZaloAccountConfig(cfg: OpenClawConfig, accountId: string): ZaloAccountConfig {
|
||||
const raw = (cfg.channels?.zalo ?? {}) as ZaloConfig;
|
||||
const { accounts: _ignored, defaultAccount: _ignored2, ...base } = raw;
|
||||
const account = resolveAccountConfig(cfg, accountId) ?? {};
|
||||
return { ...base, ...account };
|
||||
return mergeAccountConfig<ZaloAccountConfig>({
|
||||
channelConfig: cfg.channels?.zalo as ZaloAccountConfig | undefined,
|
||||
accountConfig: resolveAccountConfig(cfg, accountId),
|
||||
omitKeys: ["defaultAccount"],
|
||||
});
|
||||
}
|
||||
|
||||
export function resolveZaloAccount(params: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { normalizeAccountId } from "../../routing/session-key.js";
|
||||
import { createAccountListHelpers } from "./account-helpers.js";
|
||||
import { createAccountListHelpers, mergeAccountConfig } from "./account-helpers.js";
|
||||
|
||||
const { listConfiguredAccountIds, listAccountIds, resolveDefaultAccountId } =
|
||||
createAccountListHelpers("testchannel");
|
||||
@@ -109,3 +109,50 @@ describe("createAccountListHelpers", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("mergeAccountConfig", () => {
|
||||
it("drops accounts from the base config before merging", () => {
|
||||
const merged = mergeAccountConfig<{
|
||||
enabled?: boolean;
|
||||
name?: string;
|
||||
accounts?: Record<string, { name?: string }>;
|
||||
}>({
|
||||
channelConfig: {
|
||||
enabled: true,
|
||||
accounts: {
|
||||
work: { name: "Work" },
|
||||
},
|
||||
},
|
||||
accountConfig: {
|
||||
name: "Work",
|
||||
},
|
||||
});
|
||||
|
||||
expect(merged).toEqual({
|
||||
enabled: true,
|
||||
name: "Work",
|
||||
});
|
||||
});
|
||||
|
||||
it("drops caller-specified keys from the base config before merging", () => {
|
||||
const merged = mergeAccountConfig<{
|
||||
enabled?: boolean;
|
||||
defaultAccount?: string;
|
||||
name?: string;
|
||||
}>({
|
||||
channelConfig: {
|
||||
enabled: true,
|
||||
defaultAccount: "work",
|
||||
},
|
||||
accountConfig: {
|
||||
name: "Work",
|
||||
},
|
||||
omitKeys: ["defaultAccount"],
|
||||
});
|
||||
|
||||
expect(merged).toEqual({
|
||||
enabled: true,
|
||||
name: "Work",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -60,3 +60,20 @@ export function createAccountListHelpers(
|
||||
|
||||
return { listConfiguredAccountIds, listAccountIds, resolveDefaultAccountId };
|
||||
}
|
||||
|
||||
export function mergeAccountConfig<TConfig extends Record<string, unknown>>(params: {
|
||||
channelConfig: TConfig | undefined;
|
||||
accountConfig: Partial<TConfig> | undefined;
|
||||
omitKeys?: string[];
|
||||
}): TConfig {
|
||||
const omitKeys = new Set(["accounts", ...(params.omitKeys ?? [])]);
|
||||
const base = Object.fromEntries(
|
||||
Object.entries((params.channelConfig ?? {}) as Record<string, unknown>).filter(
|
||||
([key]) => !omitKeys.has(key),
|
||||
),
|
||||
) as TConfig;
|
||||
return {
|
||||
...base,
|
||||
...params.accountConfig,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
export { createAccountListHelpers } from "../channels/plugins/account-helpers.js";
|
||||
export {
|
||||
createAccountListHelpers,
|
||||
mergeAccountConfig,
|
||||
} from "../channels/plugins/account-helpers.js";
|
||||
export { createAccountActionGate } from "../channels/plugins/account-action-gate.js";
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
export type { OpenClawConfig } from "../config/config.js";
|
||||
|
||||
export { createAccountActionGate } from "../channels/plugins/account-action-gate.js";
|
||||
export { createAccountListHelpers } from "../channels/plugins/account-helpers.js";
|
||||
export {
|
||||
createAccountListHelpers,
|
||||
mergeAccountConfig,
|
||||
} from "../channels/plugins/account-helpers.js";
|
||||
export { normalizeChatType } from "../channels/chat-type.js";
|
||||
export { resolveAccountEntry } from "../routing/account-lookup.js";
|
||||
export {
|
||||
|
||||
Reference in New Issue
Block a user