refactor: dedupe command lowercase helpers

This commit is contained in:
Peter Steinberger
2026-04-07 12:15:16 +01:00
parent 4091fe17b9
commit 768f2fdc47
4 changed files with 32 additions and 15 deletions

View File

@@ -9,6 +9,7 @@ import type { ChannelId, ChannelPlugin } from "../../channels/plugins/types.js";
import type { OpenClawConfig } from "../../config/config.js";
import { normalizePluginsConfig, resolveEnableState } from "../../plugins/config-state.js";
import type { RuntimeEnv } from "../../runtime.js";
import { normalizeOptionalLowercaseString } from "../../shared/string-coerce.js";
import { createClackPrompter } from "../../wizard/clack-prompter.js";
import type { WizardPrompter } from "../../wizard/prompts.js";
import {
@@ -48,16 +49,18 @@ function resolveResolvedChannelId(params: {
}
export function resolveCatalogChannelEntry(raw: string, cfg: OpenClawConfig | null) {
const trimmed = raw.trim().toLowerCase();
const trimmed = normalizeOptionalLowercaseString(raw);
if (!trimmed) {
return undefined;
}
const workspaceDir = cfg ? resolveWorkspaceDir(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,
);
});
}
@@ -96,15 +99,20 @@ function resolveTrustedCatalogEntry(params: {
return params.catalogEntry;
}
if (params.rawChannel) {
const trimmed = params.rawChannel.trim().toLowerCase();
const trimmed = normalizeOptionalLowercaseString(params.rawChannel);
if (!trimmed) {
return undefined;
}
return listChannelPluginCatalogEntries({
workspaceDir: params.workspaceDir,
excludeWorkspace: true,
}).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,
);
});
}
if (!params.channelId) {

View File

@@ -1,6 +1,7 @@
import type { ModelRegistry } from "@mariozechner/pi-coding-agent";
import { parseModelRef } from "../../agents/model-selection.js";
import type { RuntimeEnv } from "../../runtime.js";
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
import { resolveConfiguredEntries } from "./list.configured.js";
import { formatErrorWithStack } from "./list.errors.js";
import {
@@ -37,7 +38,7 @@ export async function modelsListCommand(
return undefined;
}
const parsed = parseModelRef(`${raw}/_`, DEFAULT_PROVIDER);
return parsed?.provider ?? raw.toLowerCase();
return parsed?.provider ?? normalizeLowercaseStringOrEmpty(raw);
})();
let modelRegistry: ModelRegistry | undefined;

View File

@@ -6,6 +6,10 @@ import type { ModelProviderConfig } from "../config/types.models.js";
import { isSecretRef, type SecretInput } from "../config/types.secrets.js";
import { OLLAMA_DEFAULT_BASE_URL } from "../plugins/provider-model-defaults.js";
import type { RuntimeEnv } from "../runtime.js";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalLowercaseString,
} from "../shared/string-coerce.js";
import { fetchWithTimeout } from "../utils/fetch-timeout.js";
import {
normalizeSecretInput,
@@ -32,7 +36,7 @@ function normalizeContextWindowForCustomModel(value: unknown): number {
function isAzureFoundryUrl(baseUrl: string): boolean {
try {
const url = new URL(baseUrl);
const host = url.hostname.toLowerCase();
const host = normalizeLowercaseStringOrEmpty(url.hostname);
return host.endsWith(".services.ai.azure.com");
} catch {
return false;
@@ -42,7 +46,7 @@ function isAzureFoundryUrl(baseUrl: string): boolean {
function isAzureOpenAiUrl(baseUrl: string): boolean {
try {
const url = new URL(baseUrl);
const host = url.hostname.toLowerCase();
const host = normalizeLowercaseStringOrEmpty(url.hostname);
return host.endsWith(".openai.azure.com");
} catch {
return false;
@@ -92,7 +96,10 @@ function transformAzureConfigUrl(baseUrl: string): string {
function hasSameHost(a: string, b: string): boolean {
try {
return new URL(a).hostname.toLowerCase() === new URL(b).hostname.toLowerCase();
return (
normalizeLowercaseStringOrEmpty(new URL(a).hostname) ===
normalizeLowercaseStringOrEmpty(new URL(b).hostname)
);
} catch {
return false;
}
@@ -185,7 +192,7 @@ const COMPATIBILITY_OPTIONS: Array<{
];
function normalizeEndpointId(raw: string): string {
const trimmed = raw.trim().toLowerCase();
const trimmed = normalizeOptionalLowercaseString(raw);
if (!trimmed) {
return "";
}
@@ -195,7 +202,7 @@ function normalizeEndpointId(raw: string): string {
function buildEndpointIdFromUrl(baseUrl: string): string {
try {
const url = new URL(baseUrl);
const host = url.hostname.replace(/[^a-z0-9]+/gi, "-").toLowerCase();
const host = normalizeLowercaseStringOrEmpty(url.hostname.replace(/[^a-z0-9]+/gi, "-"));
const port = url.port ? `-${url.port}` : "";
const candidate = `custom-${host}${port}`;
return normalizeEndpointId(candidate) || "custom";
@@ -246,7 +253,7 @@ function resolveAliasError(params: {
cfg: params.cfg,
defaultProvider: DEFAULT_PROVIDER,
});
const aliasKey = normalized.toLowerCase();
const aliasKey = normalizeLowercaseStringOrEmpty(normalized);
const existing = aliasIndex.byAlias.get(aliasKey);
if (!existing) {
return undefined;
@@ -524,7 +531,7 @@ function resolveProviderApi(
}
function parseCustomApiCompatibility(raw?: string): CustomApiCompatibility {
const compatibilityRaw = raw?.trim().toLowerCase();
const compatibilityRaw = normalizeOptionalLowercaseString(raw);
if (!compatibilityRaw) {
return "openai";
}

View File

@@ -5,6 +5,7 @@ import { normalizeControlUiBasePath } from "../gateway/control-ui-shared.js";
import { resolveGatewayProbeTarget } from "../gateway/probe-target.js";
import type { probeGateway as probeGatewayFn } from "../gateway/probe.js";
import type { MemoryProviderStatus } from "../memory-host-sdk/engine-storage.js";
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
import { pickGatewaySelfPresence } from "./gateway-presence.js";
export { pickGatewaySelfPresence } from "./gateway-presence.js";
@@ -69,7 +70,7 @@ export function resolveMemoryPluginStatus(cfg: OpenClawConfig): MemoryPluginStat
return { enabled: false, slot: null, reason: "plugins disabled" };
}
const raw = typeof cfg.plugins?.slots?.memory === "string" ? cfg.plugins.slots.memory.trim() : "";
if (raw && raw.toLowerCase() === "none") {
if (normalizeOptionalLowercaseString(raw) === "none") {
return { enabled: false, slot: null, reason: 'plugins.slots.memory="none"' };
}
return { enabled: true, slot: raw || "memory-core" };