mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 09:41:11 +00:00
Config: split static channel configured helper
This commit is contained in:
44
src/config/channel-configured-shared.ts
Normal file
44
src/config/channel-configured-shared.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { hasNonEmptyString } from "../infra/outbound/channel-target.js";
|
||||
import { isRecord } from "../utils.js";
|
||||
import type { OpenClawConfig } from "./config.js";
|
||||
|
||||
const STATIC_ENV_RULES: Record<string, string[] | ((env: NodeJS.ProcessEnv) => boolean)> = {
|
||||
discord: ["DISCORD_BOT_TOKEN"],
|
||||
slack: ["SLACK_BOT_TOKEN"],
|
||||
telegram: ["TELEGRAM_BOT_TOKEN"],
|
||||
irc: (env) => hasNonEmptyString(env.IRC_HOST) && hasNonEmptyString(env.IRC_NICK),
|
||||
};
|
||||
|
||||
export function resolveChannelConfigRecord(
|
||||
cfg: OpenClawConfig,
|
||||
channelId: string,
|
||||
): Record<string, unknown> | null {
|
||||
const channels = cfg.channels as Record<string, unknown> | undefined;
|
||||
const entry = channels?.[channelId];
|
||||
return isRecord(entry) ? entry : null;
|
||||
}
|
||||
|
||||
export function hasMeaningfulChannelConfigShallow(value: unknown): boolean {
|
||||
if (!isRecord(value)) {
|
||||
return false;
|
||||
}
|
||||
return Object.keys(value).some((key) => key !== "enabled");
|
||||
}
|
||||
|
||||
export function isStaticallyChannelConfigured(
|
||||
cfg: OpenClawConfig,
|
||||
channelId: string,
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): boolean {
|
||||
const staticRule = STATIC_ENV_RULES[channelId];
|
||||
if (Array.isArray(staticRule)) {
|
||||
for (const envVar of staticRule) {
|
||||
if (hasNonEmptyString(env[envVar])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (staticRule?.(env)) {
|
||||
return true;
|
||||
}
|
||||
return hasMeaningfulChannelConfigShallow(resolveChannelConfigRecord(cfg, channelId));
|
||||
}
|
||||
@@ -1,24 +1,12 @@
|
||||
import { hasMeaningfulChannelConfig } from "../channels/config-presence.js";
|
||||
import { getBootstrapChannelPlugin } from "../channels/plugins/bootstrap-registry.js";
|
||||
import { hasBundledChannelConfiguredState } from "../channels/plugins/configured-state.js";
|
||||
import { hasBundledChannelPersistedAuthState } from "../channels/plugins/persisted-auth-state.js";
|
||||
import { isRecord } from "../utils.js";
|
||||
import {
|
||||
hasMeaningfulChannelConfigShallow,
|
||||
resolveChannelConfigRecord,
|
||||
} from "./channel-configured-shared.js";
|
||||
import type { OpenClawConfig } from "./config.js";
|
||||
|
||||
function resolveChannelConfig(
|
||||
cfg: OpenClawConfig,
|
||||
channelId: string,
|
||||
): Record<string, unknown> | null {
|
||||
const channels = cfg.channels as Record<string, unknown> | undefined;
|
||||
const entry = channels?.[channelId];
|
||||
return isRecord(entry) ? entry : null;
|
||||
}
|
||||
|
||||
function isGenericChannelConfigured(cfg: OpenClawConfig, channelId: string): boolean {
|
||||
const entry = resolveChannelConfig(cfg, channelId);
|
||||
return hasMeaningfulChannelConfig(entry);
|
||||
}
|
||||
|
||||
export function isChannelConfigured(
|
||||
cfg: OpenClawConfig,
|
||||
channelId: string,
|
||||
@@ -31,7 +19,7 @@ export function isChannelConfigured(
|
||||
if (pluginPersistedAuthState) {
|
||||
return true;
|
||||
}
|
||||
if (isGenericChannelConfigured(cfg, channelId)) {
|
||||
if (hasMeaningfulChannelConfigShallow(resolveChannelConfigRecord(cfg, channelId))) {
|
||||
return true;
|
||||
}
|
||||
const plugin = getBootstrapChannelPlugin(channelId);
|
||||
|
||||
@@ -20,7 +20,7 @@ describe("plugin activation boundary", () => {
|
||||
let ambientImportsPromise: Promise<void> | undefined;
|
||||
let configHelpersPromise:
|
||||
| Promise<{
|
||||
isChannelConfigured: typeof import("./config/channel-configured.js").isChannelConfigured;
|
||||
isStaticallyChannelConfigured: typeof import("./config/channel-configured-shared.js").isStaticallyChannelConfigured;
|
||||
resolveEnvApiKey: typeof import("./agents/model-auth-env.js").resolveEnvApiKey;
|
||||
}>
|
||||
| undefined;
|
||||
@@ -58,10 +58,10 @@ describe("plugin activation boundary", () => {
|
||||
|
||||
function importConfigHelpers() {
|
||||
configHelpersPromise ??= Promise.all([
|
||||
import("./config/channel-configured.js"),
|
||||
import("./config/channel-configured-shared.js"),
|
||||
import("./agents/model-auth-env.js"),
|
||||
]).then(([channelConfigured, modelAuthEnv]) => ({
|
||||
isChannelConfigured: channelConfigured.isChannelConfigured,
|
||||
isStaticallyChannelConfigured: channelConfigured.isStaticallyChannelConfigured,
|
||||
resolveEnvApiKey: modelAuthEnv.resolveEnvApiKey,
|
||||
}));
|
||||
return configHelpersPromise;
|
||||
@@ -116,15 +116,20 @@ describe("plugin activation boundary", () => {
|
||||
});
|
||||
|
||||
it("does not load bundled plugins for config and env detection helpers", async () => {
|
||||
const { isChannelConfigured, resolveEnvApiKey } = await importConfigHelpers();
|
||||
const { isStaticallyChannelConfigured, resolveEnvApiKey } = await importConfigHelpers();
|
||||
|
||||
expect(isChannelConfigured({}, "telegram", { TELEGRAM_BOT_TOKEN: "token" })).toBe(true);
|
||||
expect(isChannelConfigured({}, "discord", { DISCORD_BOT_TOKEN: "token" })).toBe(true);
|
||||
expect(isChannelConfigured({}, "slack", { SLACK_BOT_TOKEN: "xoxb-test" })).toBe(true);
|
||||
expect(isStaticallyChannelConfigured({}, "telegram", { TELEGRAM_BOT_TOKEN: "token" })).toBe(
|
||||
true,
|
||||
);
|
||||
expect(isStaticallyChannelConfigured({}, "discord", { DISCORD_BOT_TOKEN: "token" })).toBe(true);
|
||||
expect(isStaticallyChannelConfigured({}, "slack", { SLACK_BOT_TOKEN: "xoxb-test" })).toBe(true);
|
||||
expect(
|
||||
isChannelConfigured({}, "irc", { IRC_HOST: "irc.example.com", IRC_NICK: "openclaw" }),
|
||||
isStaticallyChannelConfigured({}, "irc", {
|
||||
IRC_HOST: "irc.example.com",
|
||||
IRC_NICK: "openclaw",
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(isChannelConfigured({}, "whatsapp", {})).toBe(false);
|
||||
expect(isStaticallyChannelConfigured({}, "whatsapp", {})).toBe(false);
|
||||
expect(
|
||||
resolveEnvApiKey("anthropic-vertex", {
|
||||
ANTHROPIC_VERTEX_USE_GCP_METADATA: "true",
|
||||
|
||||
Reference in New Issue
Block a user