From 75fab4fbc6cdaf9cf7bf0e95f1131ecb431f6400 Mon Sep 17 00:00:00 2001 From: Dallin Romney Date: Fri, 3 Jul 2026 16:38:02 -0700 Subject: [PATCH] refactor: remove redundant unique-list aliases (#99702) --- src/agents/api-key-rotation.ts | 11 +++++------ src/agents/model-catalog-scope.ts | 13 ++++--------- .../plugins/directory-config-helpers.ts | 18 +++++++----------- src/channels/plugins/session-conversation.ts | 14 ++++++-------- src/cli/channel-options.test.ts | 2 +- src/cli/channel-options.ts | 10 ++++------ src/infra/diagnostic-flags.ts | 6 +----- 7 files changed, 28 insertions(+), 46 deletions(-) diff --git a/src/agents/api-key-rotation.ts b/src/agents/api-key-rotation.ts index f7b7112e034..be85a38ef6d 100644 --- a/src/agents/api-key-rotation.ts +++ b/src/agents/api-key-rotation.ts @@ -30,17 +30,16 @@ type ExecuteWithApiKeyRotationOptions = { transientRetry?: TransientProviderRetryConfig; }; -function dedupeApiKeys(raw: string[]): string[] { - return normalizeUniqueStringEntries(raw); -} - /** Collect primary and live-discovered provider keys in stable de-duped order. */ export function collectProviderApiKeysForExecution(params: { provider: string; primaryApiKey?: string; }): string[] { const { primaryApiKey, provider } = params; - return dedupeApiKeys([primaryApiKey?.trim() ?? "", ...collectProviderApiKeys(provider)]); + return normalizeUniqueStringEntries([ + primaryApiKey?.trim() ?? "", + ...collectProviderApiKeys(provider), + ]); } /** @@ -50,7 +49,7 @@ export function collectProviderApiKeysForExecution(params: { export async function executeWithApiKeyRotation( params: ExecuteWithApiKeyRotationOptions, ): Promise { - const keys = dedupeApiKeys(params.apiKeys); + const keys = normalizeUniqueStringEntries(params.apiKeys); if (keys.length === 0) { throw new Error(`No API keys configured for provider "${params.provider}".`); } diff --git a/src/agents/model-catalog-scope.ts b/src/agents/model-catalog-scope.ts index 59451d612c8..6a1d909df9b 100644 --- a/src/agents/model-catalog-scope.ts +++ b/src/agents/model-catalog-scope.ts @@ -8,12 +8,6 @@ import { import { normalizeUniqueSingleOrTrimmedStringList } from "@openclaw/normalization-core/string-normalization"; import type { OpenClawConfig } from "../config/types.openclaw.js"; -// Scope refs feed provider discovery and model catalog lookups. Keep the -// ordering deterministic so prompt/cache inputs do not drift across runs. -function dedupeCatalogScopeRefs(values: Array): string[] { - return normalizeUniqueSingleOrTrimmedStringList(values); -} - // Accept provider/model refs in addition to separate provider fields so aliases // and user-entered model refs discover the owning provider catalog. function providerFromModelRef(value: string | undefined): string | undefined { @@ -52,9 +46,10 @@ export function resolveModelCatalogScope(params: { const modelRefs = providerConfigDeclaresModel(providerConfig, model) ? [provider && model ? `${provider}/${model}` : model] : [provider && model ? `${provider}/${model}` : model, model]; + // Scope ordering feeds deterministic discovery and prompt/cache inputs. return { - providerRefs: dedupeCatalogScopeRefs([provider, providerConfig?.api]), - modelRefs: dedupeCatalogScopeRefs(modelRefs), + providerRefs: normalizeUniqueSingleOrTrimmedStringList([provider, providerConfig?.api]), + modelRefs: normalizeUniqueSingleOrTrimmedStringList(modelRefs), }; } @@ -63,7 +58,7 @@ export function resolveProviderDiscoveryProviderIdsForCatalogScope(params: { providerRefs?: readonly string[]; modelRefs?: readonly string[]; }): string[] | undefined { - const providerIds = dedupeCatalogScopeRefs([ + const providerIds = normalizeUniqueSingleOrTrimmedStringList([ ...(params.providerRefs ?? []), ...(params.modelRefs ?? []).map(providerFromModelRef), ]); diff --git a/src/channels/plugins/directory-config-helpers.ts b/src/channels/plugins/directory-config-helpers.ts index ca4f87477a0..c26babcacbc 100644 --- a/src/channels/plugins/directory-config-helpers.ts +++ b/src/channels/plugins/directory-config-helpers.ts @@ -86,10 +86,6 @@ function collectDirectoryIds( return ids; } -function dedupeDirectoryIds(ids: string[]): string[] { - return uniqueStrings(ids); -} - /** * Collects unique normalized ids from multiple raw config sources. */ @@ -97,7 +93,7 @@ export function collectNormalizedDirectoryIds(params: { sources: Iterable[]; normalizeId: (entry: string) => string | null | undefined; }): string[] { - const ids = new Set(); + const ids: string[] = []; for (const source of params.sources) { for (const value of source) { const raw = normalizeOptionalString(value) ?? ""; @@ -107,11 +103,11 @@ export function collectNormalizedDirectoryIds(params: { const normalized = params.normalizeId(raw); const trimmed = normalizeOptionalString(normalized) ?? ""; if (trimmed) { - ids.add(trimmed); + ids.push(trimmed); } } } - return Array.from(ids); + return uniqueStrings(ids); } /** @@ -229,7 +225,7 @@ export function listDirectoryUserEntriesFromAllowFrom(params: { limit?: number | null; normalizeId?: (entry: string) => string | null | undefined; }): ChannelDirectoryEntry[] { - const ids = dedupeDirectoryIds( + const ids = uniqueStrings( collectDirectoryIdsFromEntries({ entries: params.allowFrom, normalizeId: params.normalizeId, @@ -249,7 +245,7 @@ export function listDirectoryUserEntriesFromAllowFromAndMapKeys(params: { normalizeAllowFromId?: (entry: string) => string | null | undefined; normalizeMapKeyId?: (entry: string) => string | null | undefined; }): ChannelDirectoryEntry[] { - const ids = dedupeDirectoryIds([ + const ids = uniqueStrings([ ...collectDirectoryIdsFromEntries({ entries: params.allowFrom, normalizeId: params.normalizeAllowFromId, @@ -271,7 +267,7 @@ export function listDirectoryGroupEntriesFromMapKeys(params: { limit?: number | null; normalizeId?: (entry: string) => string | null | undefined; }): ChannelDirectoryEntry[] { - const ids = dedupeDirectoryIds( + const ids = uniqueStrings( collectDirectoryIdsFromMapKeys({ groups: params.groups, normalizeId: params.normalizeId, @@ -291,7 +287,7 @@ export function listDirectoryGroupEntriesFromMapKeysAndAllowFrom(params: { normalizeMapKeyId?: (entry: string) => string | null | undefined; normalizeAllowFromId?: (entry: string) => string | null | undefined; }): ChannelDirectoryEntry[] { - const ids = dedupeDirectoryIds([ + const ids = uniqueStrings([ ...collectDirectoryIdsFromMapKeys({ groups: params.groups, normalizeId: params.normalizeMapKeyId, diff --git a/src/channels/plugins/session-conversation.ts b/src/channels/plugins/session-conversation.ts index e9db9e73cb4..29324c1f68e 100644 --- a/src/channels/plugins/session-conversation.ts +++ b/src/channels/plugins/session-conversation.ts @@ -88,10 +88,6 @@ function getMessagingAdapter(channel: string) { } } -function dedupeConversationIds(values: Array): string[] { - return normalizeUniqueSingleOrTrimmedStringList(values); -} - function buildGenericConversationResolution(rawId: string): ResolvedSessionConversation | null { const trimmed = rawId.trim(); if (!trimmed) { @@ -110,7 +106,7 @@ function buildGenericConversationResolution(rawId: string): ResolvedSessionConve id, threadId: parsed.threadId, baseConversationId: id, - parentConversationCandidates: dedupeConversationIds( + parentConversationCandidates: normalizeUniqueSingleOrTrimmedStringList( parsed.threadId ? [parsed.baseSessionKey] : [], ), }; @@ -130,9 +126,11 @@ function normalizeSessionConversationResolution( // candidate so nested topic/thread routes still collapse to their parent. baseConversationId: normalizeOptionalString(resolved.baseConversationId) ?? - dedupeConversationIds(resolved.parentConversationCandidates ?? []).at(-1) ?? + normalizeUniqueSingleOrTrimmedStringList(resolved.parentConversationCandidates ?? []).at( + -1, + ) ?? resolved.id.trim(), - parentConversationCandidates: dedupeConversationIds( + parentConversationCandidates: normalizeUniqueSingleOrTrimmedStringList( resolved.parentConversationCandidates ?? [], ), hasExplicitParentConversationCandidates: Object.hasOwn( @@ -229,7 +227,7 @@ function resolveSessionConversationResolution(params: { return null; } - const parentConversationCandidates = dedupeConversationIds( + const parentConversationCandidates = normalizeUniqueSingleOrTrimmedStringList( pluginResolved?.hasExplicitParentConversationCandidates ? resolved.parentConversationCandidates : (messaging?.resolveParentConversationCandidates?.({ diff --git a/src/cli/channel-options.test.ts b/src/cli/channel-options.test.ts index c12d06f3a93..003b770d667 100644 --- a/src/cli/channel-options.test.ts +++ b/src/cli/channel-options.test.ts @@ -32,7 +32,7 @@ describe("resolveCliChannelOptions", () => { it("uses precomputed startup metadata when available", () => { readFileSyncMock.mockReturnValue( - JSON.stringify({ channelOptions: ["cached", "quietchat", "cached"] }), + JSON.stringify({ channelOptions: ["cached", "", false, "quietchat", "cached"] }), ); expect(resolveCliChannelOptions()).toEqual(["cached", "quietchat"]); diff --git a/src/cli/channel-options.ts b/src/cli/channel-options.ts index 962db3e0af4..d1adf57c3c2 100644 --- a/src/cli/channel-options.ts +++ b/src/cli/channel-options.ts @@ -2,10 +2,6 @@ import { uniqueStrings } from "@openclaw/normalization-core/string-normalization"; import { readCliStartupMetadata } from "./startup-metadata.js"; -function dedupe(values: string[]): string[] { - return uniqueStrings(values.filter(Boolean)); -} - let precomputedChannelOptions: string[] | null | undefined; function loadPrecomputedChannelOptions(): string[] | null { @@ -15,8 +11,10 @@ function loadPrecomputedChannelOptions(): string[] | null { try { const parsed = readCliStartupMetadata(import.meta.url) as { channelOptions?: unknown } | null; if (parsed && Array.isArray(parsed.channelOptions)) { - precomputedChannelOptions = dedupe( - parsed.channelOptions.filter((value): value is string => typeof value === "string"), + precomputedChannelOptions = uniqueStrings( + parsed.channelOptions.filter( + (value): value is string => typeof value === "string" && Boolean(value), + ), ); return precomputedChannelOptions; } diff --git a/src/infra/diagnostic-flags.ts b/src/infra/diagnostic-flags.ts index ea0b3c7dc3a..83526401b4f 100644 --- a/src/infra/diagnostic-flags.ts +++ b/src/infra/diagnostic-flags.ts @@ -34,10 +34,6 @@ function parseEnvFlags(raw?: string): ParsedEnvFlags { }; } -function uniqueFlags(flags: string[]): string[] { - return normalizeUniqueStringEntriesLower(flags); -} - /** Resolves enabled diagnostic flags from config plus `OPENCLAW_DIAGNOSTICS` overrides. */ export function resolveDiagnosticFlags( cfg?: OpenClawConfig, @@ -48,7 +44,7 @@ export function resolveDiagnosticFlags( if (envFlags.disablesAll) { return []; } - return uniqueFlags([...configFlags, ...envFlags.flags]); + return normalizeUniqueStringEntriesLower([...configFlags, ...envFlags.flags]); } /** Matches one diagnostic flag against exact, wildcard, and namespace-enabled flags. */