refactor: share trimmed string entry normalization

This commit is contained in:
Peter Steinberger
2026-03-07 23:11:04 +00:00
parent 6647d02846
commit d228a62143
12 changed files with 29 additions and 15 deletions

View File

@@ -1,3 +1,4 @@
import { normalizeStringEntries } from "../../shared/string-normalization.js";
import { normalizeSecretInput } from "../../utils/normalize-secret-input.js";
import { normalizeProviderId, normalizeProviderIdForAuth } from "../model-selection.js";
import {
@@ -18,9 +19,7 @@ export async function setAuthProfileOrder(params: {
}): Promise<AuthProfileStore | null> {
const providerKey = normalizeProviderId(params.provider);
const sanitized =
params.order && Array.isArray(params.order)
? params.order.map((entry) => String(entry).trim()).filter(Boolean)
: [];
params.order && Array.isArray(params.order) ? normalizeStringEntries(params.order) : [];
const deduped = dedupeProfileIds(sanitized);
return await updateAuthProfileStoreWithLock({

View File

@@ -6,6 +6,7 @@ import {
resolveConfigPath,
resolveRuntimePlatform,
} from "../../shared/config-eval.js";
import { normalizeStringEntries } from "../../shared/string-normalization.js";
import { resolveSkillKey } from "./frontmatter.js";
import type { SkillEligibilityContext, SkillEntry } from "./types.js";
@@ -42,7 +43,7 @@ function normalizeAllowlist(input: unknown): string[] | undefined {
if (!Array.isArray(input)) {
return undefined;
}
const normalized = input.map((entry) => String(entry).trim()).filter(Boolean);
const normalized = normalizeStringEntries(input);
return normalized.length > 0 ? normalized : undefined;
}

View File

@@ -1,8 +1,10 @@
import { normalizeStringEntries } from "../../shared/string-normalization.js";
export function normalizeSkillFilter(skillFilter?: ReadonlyArray<unknown>): string[] | undefined {
if (skillFilter === undefined) {
return undefined;
}
return skillFilter.map((entry) => String(entry).trim()).filter(Boolean);
return normalizeStringEntries(skillFilter);
}
export function normalizeSkillFilterForComparison(

View File

@@ -3,6 +3,7 @@ import { getChannelDock, listChannelDocks } from "../channels/dock.js";
import type { ChannelId } from "../channels/plugins/types.js";
import { normalizeAnyChannelId } from "../channels/registry.js";
import type { OpenClawConfig } from "../config/config.js";
import { normalizeStringEntries } from "../shared/string-normalization.js";
import {
INTERNAL_MESSAGE_CHANNEL,
isInternalMessageChannel,
@@ -85,7 +86,7 @@ function formatAllowFromList(params: {
if (dock?.config?.formatAllowFrom) {
return dock.config.formatAllowFrom({ cfg, accountId, allowFrom });
}
return allowFrom.map((entry) => String(entry).trim()).filter(Boolean);
return normalizeStringEntries(allowFrom);
}
function normalizeAllowFromEntry(params: {

View File

@@ -23,6 +23,7 @@ import {
normalizeAccountId,
normalizeOptionalAccountId,
} from "../../routing/session-key.js";
import { normalizeStringEntries } from "../../shared/string-normalization.js";
import { resolveSignalAccount } from "../../signal/accounts.js";
import { resolveSlackAccount } from "../../slack/accounts.js";
import { resolveSlackUserAllowlist } from "../../slack/resolve-users.js";
@@ -165,7 +166,7 @@ function normalizeAllowFrom(params: {
allowFrom: params.values,
});
}
return params.values.map((entry) => String(entry).trim()).filter(Boolean);
return normalizeStringEntries(params.values);
}
function formatEntryList(entries: string[], resolved?: Map<string, string>): string {

View File

@@ -12,6 +12,7 @@ import { type OpenClawConfig, loadConfig } from "../../config/config.js";
import { applyLinkUnderstanding } from "../../link-understanding/apply.js";
import { applyMediaUnderstanding } from "../../media-understanding/apply.js";
import { defaultRuntime } from "../../runtime.js";
import { normalizeStringEntries } from "../../shared/string-normalization.js";
import { resolveCommandAuthorization } from "../command-auth.js";
import type { MsgContext } from "../templating.js";
import { SILENT_REPLY_TOKEN } from "../tokens.js";
@@ -33,7 +34,7 @@ function mergeSkillFilters(channelFilter?: string[], agentFilter?: string[]): st
if (!Array.isArray(list)) {
return undefined;
}
return list.map((entry) => String(entry).trim()).filter(Boolean);
return normalizeStringEntries(list);
};
const channel = normalize(channelFilter);
const agent = normalize(agentFilter);

View File

@@ -2,6 +2,7 @@ import { resolveAgentConfig } from "../../agents/agent-scope.js";
import { getChannelDock } from "../../channels/dock.js";
import { normalizeChannelId } from "../../channels/plugins/index.js";
import type { AgentElevatedAllowFromConfig, OpenClawConfig } from "../../config/config.js";
import { normalizeStringEntries } from "../../shared/string-normalization.js";
import type { MsgContext } from "../templating.js";
import {
type AllowFromFormatter,
@@ -36,7 +37,7 @@ function resolveAllowFromFormatter(params: {
const dock = normalizedProvider ? getChannelDock(normalizedProvider) : undefined;
const formatAllowFrom = dock?.config?.formatAllowFrom;
if (!formatAllowFrom) {
return (values) => values.map((entry) => String(entry).trim()).filter(Boolean);
return (values) => normalizeStringEntries(values);
}
return (values) =>
formatAllowFrom({
@@ -64,7 +65,7 @@ function isApprovedElevatedSender(params: {
return false;
}
const allowTokens = rawAllow.map((entry) => String(entry).trim()).filter(Boolean);
const allowTokens = normalizeStringEntries(rawAllow);
if (allowTokens.length === 0) {
return false;
}

View File

@@ -1,4 +1,5 @@
import type { OpenClawConfig } from "../config/config.js";
import { normalizeStringEntries } from "../shared/string-normalization.js";
import { projectSafeChannelAccountSnapshotFields } from "./account-snapshot-fields.js";
import type { ChannelAccountSnapshot } from "./plugins/types.core.js";
import type { ChannelPlugin } from "./plugins/types.plugin.js";
@@ -34,7 +35,7 @@ export function formatChannelAllowFrom(params: {
allowFrom: params.allowFrom,
});
}
return params.allowFrom.map((entry) => String(entry).trim()).filter(Boolean);
return normalizeStringEntries(params.allowFrom);
}
function asRecord(value: unknown): Record<string, unknown> | undefined {

View File

@@ -6,6 +6,7 @@ import {
} from "../../agents/auth-profiles.js";
import { normalizeProviderId } from "../../agents/model-selection.js";
import type { RuntimeEnv } from "../../runtime.js";
import { normalizeStringEntries } from "../../shared/string-normalization.js";
import { shortenHomePath } from "../../utils.js";
import { loadModelsConfig } from "./load-config.js";
import { resolveKnownAgentId } from "./shared.js";
@@ -104,7 +105,7 @@ export async function modelsAuthOrderSetCommand(
allowKeychainPrompt: false,
});
const providerKey = provider;
const requested = (opts.order ?? []).map((entry) => String(entry).trim()).filter(Boolean);
const requested = normalizeStringEntries(opts.order ?? []);
if (requested.length === 0) {
throw new Error("Missing profile ids. Provide one or more profile ids.");
}

View File

@@ -2,6 +2,7 @@ import { normalizeWhatsAppAllowFromEntries } from "../channels/plugins/normalize
import type { OpenClawConfig } from "../config/config.js";
import { resolveIMessageAccount } from "../imessage/accounts.js";
import { normalizeAccountId } from "../routing/session-key.js";
import { normalizeStringEntries } from "../shared/string-normalization.js";
import { resolveWhatsAppAccount } from "../web/accounts.js";
export function mapAllowFromEntries(
@@ -11,7 +12,7 @@ export function mapAllowFromEntries(
}
export function formatTrimmedAllowFromEntries(allowFrom: Array<string | number>): string[] {
return allowFrom.map((entry) => String(entry).trim()).filter(Boolean);
return normalizeStringEntries(allowFrom);
}
export function resolveOptionalConfigString(

View File

@@ -9,6 +9,11 @@ import {
describe("shared/string-normalization", () => {
it("normalizes mixed allow-list entries", () => {
expect(normalizeStringEntries([" a ", 42, "", " ", "z"])).toEqual(["a", "42", "z"]);
expect(normalizeStringEntries([" ok ", null, { toString: () => " obj " }])).toEqual([
"ok",
"null",
"obj",
]);
expect(normalizeStringEntries(undefined)).toEqual([]);
});

View File

@@ -1,8 +1,8 @@
export function normalizeStringEntries(list?: Array<string | number>) {
export function normalizeStringEntries(list?: ReadonlyArray<unknown>) {
return (list ?? []).map((entry) => String(entry).trim()).filter(Boolean);
}
export function normalizeStringEntriesLower(list?: Array<string | number>) {
export function normalizeStringEntriesLower(list?: ReadonlyArray<unknown>) {
return normalizeStringEntries(list).map((entry) => entry.toLowerCase());
}