refactor: remove redundant unique-list aliases (#99702)

This commit is contained in:
Dallin Romney 2026-07-03 16:38:02 -07:00 committed by GitHub
parent 603502f60f
commit 75fab4fbc6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 28 additions and 46 deletions

View file

@ -30,17 +30,16 @@ type ExecuteWithApiKeyRotationOptions<T> = {
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<T>(
params: ExecuteWithApiKeyRotationOptions<T>,
): Promise<T> {
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}".`);
}

View file

@ -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 | undefined>): 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),
]);

View file

@ -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<unknown>[];
normalizeId: (entry: string) => string | null | undefined;
}): string[] {
const ids = new Set<string>();
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,

View file

@ -88,10 +88,6 @@ function getMessagingAdapter(channel: string) {
}
}
function dedupeConversationIds(values: Array<string | undefined | null>): 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?.({

View file

@ -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"]);

View file

@ -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;
}

View file

@ -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. */