mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 09:41:11 +00:00
refactor: dedupe channel lowercase helpers
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
} from "../shared/string-coerce.js";
|
||||
|
||||
export type AllowlistMatchSource =
|
||||
| "wildcard"
|
||||
| "id"
|
||||
@@ -37,7 +42,9 @@ export function compileAllowlist(entries: ReadonlyArray<string>): CompiledAllowl
|
||||
|
||||
function compileSimpleAllowlist(entries: ReadonlyArray<string | number>): CompiledAllowlist {
|
||||
return compileAllowlist(
|
||||
entries.map((entry) => String(entry).trim().toLowerCase()).filter(Boolean),
|
||||
entries
|
||||
.map((entry) => normalizeOptionalLowercaseString(String(entry)))
|
||||
.filter((entry): entry is string => Boolean(entry)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -98,8 +105,8 @@ export function resolveAllowlistMatchSimple(params: {
|
||||
return { allowed: true, matchKey: "*", matchSource: "wildcard" };
|
||||
}
|
||||
|
||||
const senderId = params.senderId.toLowerCase();
|
||||
const senderName = params.senderName?.toLowerCase();
|
||||
const senderId = normalizeLowercaseStringOrEmpty(params.senderId);
|
||||
const senderName = normalizeOptionalLowercaseString(params.senderName);
|
||||
return resolveAllowlistCandidates({
|
||||
compiledAllowlist: allowFrom,
|
||||
candidates: [
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { mapAllowFromEntries } from "openclaw/plugin-sdk/channel-config-helpers";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
import { summarizeStringEntries } from "../../shared/string-sample.js";
|
||||
|
||||
export type AllowlistUserResolutionLike = {
|
||||
@@ -16,7 +17,7 @@ function dedupeAllowlistEntries(entries: string[]): string[] {
|
||||
if (!normalized) {
|
||||
continue;
|
||||
}
|
||||
const key = normalized.toLowerCase();
|
||||
const key = normalizeLowercaseStringOrEmpty(normalized);
|
||||
if (seen.has(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
|
||||
export type ChannelMatchSource = "direct" | "parent" | "wildcard";
|
||||
|
||||
export type ChannelEntryMatch<T> = {
|
||||
@@ -32,9 +34,7 @@ export function resolveChannelMatchConfig<
|
||||
}
|
||||
|
||||
export function normalizeChannelSlug(value: string): string {
|
||||
return value
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
return normalizeLowercaseStringOrEmpty(value)
|
||||
.replace(/^#/, "")
|
||||
.replace(/[^a-z0-9]+/g, "-")
|
||||
.replace(/^-+|-+$/g, "");
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { OpenClawConfig } from "../config/config.js";
|
||||
import { resolveConversationIdFromTargets } from "../infra/outbound/conversation-id.js";
|
||||
import { getActivePluginChannelRegistry } from "../plugins/runtime.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
@@ -78,7 +79,7 @@ function resolveChannelTargetId(params: {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const lower = target.toLowerCase();
|
||||
const lower = normalizeLowercaseStringOrEmpty(target);
|
||||
const channelPrefix = `${params.channel}:`;
|
||||
if (lower.startsWith(channelPrefix)) {
|
||||
return resolveChannelTargetId({
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
|
||||
export type ResolveNativeCommandSessionTargetsParams = {
|
||||
agentId: string;
|
||||
sessionPrefix: string;
|
||||
@@ -13,7 +15,9 @@ export function resolveNativeCommandSessionTargets(
|
||||
const rawSessionKey =
|
||||
params.boundSessionKey ?? `agent:${params.agentId}:${params.sessionPrefix}:${params.userId}`;
|
||||
return {
|
||||
sessionKey: params.lowercaseSessionKey ? rawSessionKey.toLowerCase() : rawSessionKey,
|
||||
sessionKey: params.lowercaseSessionKey
|
||||
? normalizeLowercaseStringOrEmpty(rawSessionKey)
|
||||
: rawSessionKey,
|
||||
commandTargetSessionKey: params.boundSessionKey ?? params.targetSessionKey,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ import {
|
||||
resolveDefaultAgentId,
|
||||
} from "../../agents/agent-scope.js";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
} from "../../shared/string-coerce.js";
|
||||
import type {
|
||||
ConfiguredBindingRuleConfig,
|
||||
ConfiguredBindingTargetFactory,
|
||||
@@ -26,8 +30,9 @@ function resolveAgentRuntimeAcpDefaults(params: { cfg: OpenClawConfig; ownerAgen
|
||||
cwd?: string;
|
||||
backend?: string;
|
||||
} {
|
||||
const ownerAgentId = normalizeLowercaseStringOrEmpty(params.ownerAgentId);
|
||||
const agent = params.cfg.agents?.list?.find(
|
||||
(entry) => entry.id?.trim().toLowerCase() === params.ownerAgentId.toLowerCase(),
|
||||
(entry) => normalizeOptionalLowercaseString(entry.id) === ownerAgentId,
|
||||
);
|
||||
if (!agent || agent.runtime?.type !== "acp") {
|
||||
return {};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
import { isInternalMessageChannel } from "../../utils/message-channel.js";
|
||||
import {
|
||||
authorizeConfigWriteShared,
|
||||
@@ -40,7 +41,7 @@ export function resolveExplicitConfigWriteTarget(scope: ConfigWriteScope): Confi
|
||||
export function resolveConfigWriteTargetFromPath(path: string[]): ConfigWriteTarget {
|
||||
return resolveConfigWriteTargetFromPathShared({
|
||||
path,
|
||||
normalizeChannelId: (raw) => raw.trim().toLowerCase() as ChannelId,
|
||||
normalizeChannelId: (raw) => normalizeLowercaseStringOrEmpty(raw) as ChannelId,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,10 @@ import {
|
||||
type ParsedThreadSessionSuffix,
|
||||
type RawSessionConversationRef,
|
||||
} from "../../sessions/session-key-utils.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
} from "../../shared/string-coerce.js";
|
||||
import { normalizeChannelId as normalizeChatChannelId } from "../registry.js";
|
||||
import { getLoadedChannelPlugin, normalizeChannelId as normalizeAnyChannelId } from "./registry.js";
|
||||
|
||||
@@ -55,7 +58,8 @@ function normalizeResolvedChannel(channel: string): string {
|
||||
return (
|
||||
normalizeAnyChannelId(channel) ??
|
||||
normalizeChatChannelId(channel) ??
|
||||
channel.trim().toLowerCase()
|
||||
normalizeOptionalLowercaseString(channel) ??
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
|
||||
export type { DirectoryConfigParams } from "./plugins/directory-types.js";
|
||||
export type { ChannelDirectoryEntry } from "./plugins/types.js";
|
||||
|
||||
@@ -16,7 +18,7 @@ export type MessagingTargetParseOptions = {
|
||||
};
|
||||
|
||||
export function normalizeTargetId(kind: MessagingTargetKind, id: string): string {
|
||||
return `${kind}:${id}`.toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(`${kind}:${id}`);
|
||||
}
|
||||
|
||||
export function buildMessagingTarget(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { normalizeAccountId } from "../routing/session-key.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import { getChannelPlugin } from "./plugins/index.js";
|
||||
|
||||
const DEFAULT_THREAD_BINDING_IDLE_HOURS = 24;
|
||||
@@ -28,9 +29,7 @@ export type ThreadBindingSpawnPolicy = {
|
||||
};
|
||||
|
||||
function normalizeChannelId(value: string | undefined | null): string {
|
||||
return String(value ?? "")
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(value);
|
||||
}
|
||||
|
||||
export function supportsAutomaticThreadBindingSpawn(channel: string): boolean {
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { ChannelId, ChannelPlugin, ChannelSetupInput } from "../../channels
|
||||
import { replaceConfigFile, type OpenClawConfig } from "../../config/config.js";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../routing/session-key.js";
|
||||
import { defaultRuntime, type RuntimeEnv } from "../../runtime.js";
|
||||
import { normalizeOptionalLowercaseString } from "../../shared/string-coerce.js";
|
||||
import { createClackPrompter } from "../../wizard/clack-prompter.js";
|
||||
import { applyAgentBindings, describeBinding } from "../agents.bindings.js";
|
||||
import { isCatalogChannelInstalled } from "../channel-setup/discovery.js";
|
||||
@@ -28,16 +29,18 @@ export type ChannelsAddOptions = {
|
||||
} & Omit<ChannelSetupInput, "groupChannels" | "dmAllowlist" | "initialSyncLimit">;
|
||||
|
||||
function resolveCatalogChannelEntry(raw: string, cfg: OpenClawConfig | null) {
|
||||
const trimmed = raw.trim().toLowerCase();
|
||||
const trimmed = normalizeOptionalLowercaseString(raw);
|
||||
if (!trimmed) {
|
||||
return undefined;
|
||||
}
|
||||
const workspaceDir = cfg ? resolveAgentWorkspaceDir(cfg, resolveDefaultAgentId(cfg)) : undefined;
|
||||
return listChannelPluginCatalogEntries({ workspaceDir }).find((entry) => {
|
||||
if (entry.id.toLowerCase() === trimmed) {
|
||||
if (normalizeOptionalLowercaseString(entry.id) === trimmed) {
|
||||
return true;
|
||||
}
|
||||
return (entry.meta.aliases ?? []).some((alias) => alias.trim().toLowerCase() === trimmed);
|
||||
return (entry.meta.aliases ?? []).some(
|
||||
(alias) => normalizeOptionalLowercaseString(alias) === trimmed,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,10 @@ import {
|
||||
import { danger } from "../../globals.js";
|
||||
import { formatErrorMessage } from "../../infra/errors.js";
|
||||
import { defaultRuntime, type RuntimeEnv, writeRuntimeJson } from "../../runtime.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../../shared/string-coerce.js";
|
||||
import { theme } from "../../terminal/theme.js";
|
||||
import { resolveInstallableChannelPlugin } from "../channel-setup/channel-plugin-resolution.js";
|
||||
import { formatChannelAccountLabel, requireValidConfig } from "./shared.js";
|
||||
@@ -220,7 +223,7 @@ export async function channelsCapabilitiesCommand(
|
||||
}
|
||||
let cfg = loadedCfg;
|
||||
const timeoutMs = normalizeTimeout(opts.timeout, 10_000);
|
||||
const rawChannel = typeof opts.channel === "string" ? opts.channel.trim().toLowerCase() : "";
|
||||
const rawChannel = normalizeLowercaseStringOrEmpty(opts.channel);
|
||||
const rawTarget = typeof opts.target === "string" ? opts.target.trim() : "";
|
||||
|
||||
if (opts.account && (!rawChannel || rawChannel === "all")) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { listChannelPlugins } from "../../channels/plugins/index.js";
|
||||
import { getResolvedLoggerSettings } from "../../logging.js";
|
||||
import { parseLogLine } from "../../logging/parse-log-line.js";
|
||||
import { defaultRuntime, type RuntimeEnv, writeRuntimeJson } from "../../runtime.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
import { theme } from "../../terminal/theme.js";
|
||||
|
||||
export type ChannelsLogsOptions = {
|
||||
@@ -20,7 +21,7 @@ const getChannelSet = () =>
|
||||
new Set<string>([...listChannelPlugins().map((plugin) => plugin.id), "all"]);
|
||||
|
||||
function parseChannelFilter(raw?: string) {
|
||||
const trimmed = raw?.trim().toLowerCase();
|
||||
const trimmed = normalizeLowercaseStringOrEmpty(raw);
|
||||
if (!trimmed) {
|
||||
return "all";
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@ import { loadConfig, readConfigFileSnapshot, replaceConfigFile } from "../../con
|
||||
import { danger } from "../../globals.js";
|
||||
import { resolveMessageChannelSelection } from "../../infra/outbound/channel-selection.js";
|
||||
import { type RuntimeEnv, writeRuntimeJson } from "../../runtime.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
} from "../../shared/string-coerce.js";
|
||||
import { resolveInstallableChannelPlugin } from "../channel-setup/channel-plugin-resolution.js";
|
||||
|
||||
export type ChannelsResolveOptions = {
|
||||
@@ -71,10 +75,10 @@ function detectAutoKindForPlugin(
|
||||
return generic;
|
||||
}
|
||||
const trimmed = input.trim();
|
||||
const lowered = trimmed.toLowerCase();
|
||||
const lowered = normalizeLowercaseStringOrEmpty(trimmed);
|
||||
const prefixes = [plugin.id, ...(plugin.meta?.aliases ?? [])]
|
||||
.map((entry) => entry.trim().toLowerCase())
|
||||
.filter(Boolean);
|
||||
.map((entry) => normalizeOptionalLowercaseString(entry))
|
||||
.filter((entry): entry is string => Boolean(entry));
|
||||
for (const prefix of prefixes) {
|
||||
if (!lowered.startsWith(`${prefix}:`)) {
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user