mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-14 02:31:24 +00:00
refactor: dedupe lowercase helper readers
This commit is contained in:
@@ -19,7 +19,10 @@ import { resolveSessionParentSessionKey } from "../../channels/plugins/session-c
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import type { SessionEntry } from "../../config/sessions/types.js";
|
||||
import { applyModelOverrideToSessionEntry } from "../../sessions/model-overrides.js";
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../../shared/string-coerce.js";
|
||||
import type { ThinkLevel } from "./directives.js";
|
||||
|
||||
export type ModelDirectiveSelection = {
|
||||
@@ -211,7 +214,7 @@ function scoreFuzzyMatch(params: {
|
||||
} {
|
||||
const provider = normalizeProviderId(params.provider);
|
||||
const model = params.model;
|
||||
const fragment = params.fragment.trim().toLowerCase();
|
||||
const fragment = normalizeLowercaseStringOrEmpty(params.fragment);
|
||||
const providerLower = provider.toLowerCase();
|
||||
const modelLower = model.toLowerCase();
|
||||
const haystack = `${providerLower}/${modelLower}`;
|
||||
@@ -541,7 +544,7 @@ export function resolveModelDirectiveSelection(params: {
|
||||
provider?: string;
|
||||
fragment: string;
|
||||
}): { selection?: ModelDirectiveSelection; error?: string } => {
|
||||
const fragment = params.fragment.trim().toLowerCase();
|
||||
const fragment = normalizeLowercaseStringOrEmpty(params.fragment);
|
||||
if (!fragment) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { resolveCronStyleNow } from "../../agents/current-time.js";
|
||||
import { resolveUserTimezone } from "../../agents/date-time.js";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { openBoundaryFile } from "../../infra/boundary-file-read.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
|
||||
const MAX_CONTEXT_CHARS = 3000;
|
||||
const DEFAULT_POST_COMPACTION_SECTIONS = ["Session Startup", "Red Lines"];
|
||||
@@ -18,12 +19,12 @@ function matchesSectionSet(sectionNames: string[], expectedSections: string[]):
|
||||
|
||||
const counts = new Map<string, number>();
|
||||
for (const name of expectedSections) {
|
||||
const normalized = name.trim().toLowerCase();
|
||||
const normalized = normalizeLowercaseStringOrEmpty(name);
|
||||
counts.set(normalized, (counts.get(normalized) ?? 0) + 1);
|
||||
}
|
||||
|
||||
for (const name of sectionNames) {
|
||||
const normalized = name.trim().toLowerCase();
|
||||
const normalized = normalizeLowercaseStringOrEmpty(name);
|
||||
const count = counts.get(normalized);
|
||||
if (!count) {
|
||||
return false;
|
||||
|
||||
@@ -171,7 +171,7 @@ export function resolveChannelModelOverride(
|
||||
keys,
|
||||
parentKeys,
|
||||
wildcardKey: "*",
|
||||
normalizeKey: (value) => value.trim().toLowerCase(),
|
||||
normalizeKey: (value) => normalizeOptionalLowercaseString(value) ?? "",
|
||||
});
|
||||
const raw = match.entry ?? match.wildcardEntry;
|
||||
if (typeof raw !== "string") {
|
||||
|
||||
@@ -35,6 +35,7 @@ import {
|
||||
registerMemoryEmbeddingProvider,
|
||||
} from "../plugins/memory-embedding-providers.js";
|
||||
import { writeRuntimeJson, defaultRuntime, type RuntimeEnv } from "../runtime.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import { formatDocsLink } from "../terminal/links.js";
|
||||
import { theme } from "../terminal/theme.js";
|
||||
import { canonicalizeSpeechProviderId, listSpeechProviders } from "../tts/provider-registry.js";
|
||||
@@ -1725,11 +1726,11 @@ export function registerCapabilityCli(program: Command) {
|
||||
const cfg = loadConfig();
|
||||
const selectedSearchProvider =
|
||||
typeof cfg.tools?.web?.search?.provider === "string"
|
||||
? cfg.tools.web.search.provider.trim().toLowerCase()
|
||||
? normalizeLowercaseStringOrEmpty(cfg.tools.web.search.provider)
|
||||
: "";
|
||||
const selectedFetchProvider =
|
||||
typeof cfg.tools?.web?.fetch?.provider === "string"
|
||||
? cfg.tools.web.fetch.provider.trim().toLowerCase()
|
||||
? normalizeLowercaseStringOrEmpty(cfg.tools.web.fetch.provider)
|
||||
: "";
|
||||
const result = {
|
||||
search: listWebSearchProviders({ config: cfg }).map((provider) => ({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { AuthProfileStore } from "../agents/auth-profiles.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
|
||||
|
||||
export const DEFAULT_LIVE_IMAGE_MODELS: Record<string, string> = {
|
||||
fal: "fal/fal-ai/flux/dev",
|
||||
@@ -16,8 +17,8 @@ export function parseCaseFilter(raw?: string): Set<string> | null {
|
||||
}
|
||||
const values = trimmed
|
||||
.split(",")
|
||||
.map((entry) => entry.trim().toLowerCase())
|
||||
.filter(Boolean);
|
||||
.map((entry) => normalizeOptionalLowercaseString(entry))
|
||||
.filter((entry): entry is string => Boolean(entry));
|
||||
return values.length > 0 ? new Set(values) : null;
|
||||
}
|
||||
|
||||
@@ -55,7 +56,11 @@ export function parseProviderModelMap(raw?: string): Map<string, string> {
|
||||
if (slash <= 0 || slash === trimmed.length - 1) {
|
||||
continue;
|
||||
}
|
||||
entries.set(trimmed.slice(0, slash).trim().toLowerCase(), trimmed);
|
||||
const providerId = normalizeOptionalLowercaseString(trimmed.slice(0, slash));
|
||||
if (!providerId) {
|
||||
continue;
|
||||
}
|
||||
entries.set(providerId, trimmed);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
@@ -72,7 +77,11 @@ export function resolveConfiguredLiveImageModels(cfg: OpenClawConfig): Map<strin
|
||||
if (slash <= 0 || slash === trimmed.length - 1) {
|
||||
return;
|
||||
}
|
||||
resolved.set(trimmed.slice(0, slash).trim().toLowerCase(), trimmed);
|
||||
const providerId = normalizeOptionalLowercaseString(trimmed.slice(0, slash));
|
||||
if (!providerId) {
|
||||
return;
|
||||
}
|
||||
resolved.set(providerId, trimmed);
|
||||
};
|
||||
if (typeof configured === "string") {
|
||||
add(configured);
|
||||
|
||||
@@ -2,6 +2,10 @@ import path from "node:path";
|
||||
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { asNullableRecord } from "../shared/record-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
} from "../shared/string-coerce.js";
|
||||
|
||||
export const DEFAULT_MEMORY_DREAMING_ENABLED = false;
|
||||
export const DEFAULT_MEMORY_DREAMING_TIMEZONE = undefined;
|
||||
@@ -190,7 +194,7 @@ function normalizeBoolean(value: unknown, fallback: boolean): boolean {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
const normalized = value.trim().toLowerCase();
|
||||
const normalized = normalizeLowercaseStringOrEmpty(value);
|
||||
if (normalized === "true") {
|
||||
return true;
|
||||
}
|
||||
@@ -591,7 +595,7 @@ export function resolveMemoryDreamingWorkspaces(cfg: OpenClawConfig): MemoryDrea
|
||||
if (!entry || typeof entry !== "object" || typeof entry.id !== "string") {
|
||||
continue;
|
||||
}
|
||||
const id = entry.id.trim().toLowerCase();
|
||||
const id = normalizeOptionalLowercaseString(entry.id);
|
||||
if (!id || seenAgents.has(id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
|
||||
const MEMORY_MULTIMODAL_SPECS = {
|
||||
image: {
|
||||
labelPrefix: "Image file",
|
||||
@@ -73,7 +75,7 @@ export function buildMemoryMultimodalLabel(
|
||||
}
|
||||
|
||||
export function buildCaseInsensitiveExtensionGlob(extension: string): string {
|
||||
const normalized = extension.trim().replace(/^\./, "").toLowerCase();
|
||||
const normalized = normalizeLowercaseStringOrEmpty(extension).replace(/^\./, "");
|
||||
if (!normalized) {
|
||||
return "*";
|
||||
}
|
||||
@@ -88,7 +90,7 @@ export function classifyMemoryMultimodalPath(
|
||||
if (!isMemoryMultimodalEnabled(settings)) {
|
||||
return null;
|
||||
}
|
||||
const lower = filePath.trim().toLowerCase();
|
||||
const lower = normalizeLowercaseStringOrEmpty(filePath);
|
||||
for (const modality of settings.modalities) {
|
||||
for (const extension of getMemoryMultimodalExtensions(modality)) {
|
||||
if (lower.endsWith(extension)) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { formatErrorMessage } from "../../infra/errors.js";
|
||||
import { createSubsystemLogger } from "../../logging/subsystem.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
|
||||
const log = createSubsystemLogger("memory");
|
||||
|
||||
@@ -52,7 +53,7 @@ export function parseQmdQueryJson(stdout: string, stderr: string): QmdQueryResul
|
||||
function isQmdNoResultsOutput(raw: string): boolean {
|
||||
const lines = raw
|
||||
.split(/\r?\n/)
|
||||
.map((line) => line.trim().toLowerCase().replace(/\s+/g, " "))
|
||||
.map((line) => normalizeLowercaseStringOrEmpty(line).replace(/\s+/g, " "))
|
||||
.filter((line) => line.length > 0);
|
||||
return lines.some((line) => isQmdNoResultsLine(line));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { parseAgentSessionKey } from "../../sessions/session-key-utils.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
} from "../../shared/string-coerce.js";
|
||||
import type { ResolvedQmdConfig } from "./backend-config.js";
|
||||
|
||||
type ParsedQmdSessionScope = {
|
||||
@@ -15,7 +19,7 @@ export function isQmdScopeAllowed(scope: ResolvedQmdConfig["scope"], sessionKey?
|
||||
const channel = parsed.channel;
|
||||
const chatType = parsed.chatType;
|
||||
const normalizedKey = parsed.normalizedKey ?? "";
|
||||
const rawKey = sessionKey?.trim().toLowerCase() ?? "";
|
||||
const rawKey = normalizeLowercaseStringOrEmpty(sessionKey);
|
||||
for (const rule of scope.rules ?? []) {
|
||||
if (!rule) {
|
||||
continue;
|
||||
@@ -27,8 +31,8 @@ export function isQmdScopeAllowed(scope: ResolvedQmdConfig["scope"], sessionKey?
|
||||
if (match.chatType && match.chatType !== chatType) {
|
||||
continue;
|
||||
}
|
||||
const normalizedPrefix = match.keyPrefix?.trim().toLowerCase() || undefined;
|
||||
const rawPrefix = match.rawKeyPrefix?.trim().toLowerCase() || undefined;
|
||||
const normalizedPrefix = normalizeOptionalLowercaseString(match.keyPrefix);
|
||||
const rawPrefix = normalizeOptionalLowercaseString(match.rawKeyPrefix);
|
||||
|
||||
if (rawPrefix && !rawKey.startsWith(rawPrefix)) {
|
||||
continue;
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
* This module extracts meaningful keywords from such queries to improve FTS results.
|
||||
*/
|
||||
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
|
||||
// Common stop words that don't add search value
|
||||
const STOP_WORDS_EN = new Set([
|
||||
// Articles and determiners
|
||||
@@ -673,7 +675,7 @@ function isValidKeyword(token: string): boolean {
|
||||
function tokenize(text: string, opts?: { ftsTokenizer?: "unicode61" | "trigram" }): string[] {
|
||||
const useTrigram = opts?.ftsTokenizer === "trigram";
|
||||
const tokens: string[] = [];
|
||||
const normalized = text.toLowerCase().trim();
|
||||
const normalized = normalizeLowercaseStringOrEmpty(text);
|
||||
|
||||
// Split into segments (English words, Chinese character sequences, etc.)
|
||||
const segments = normalized.split(/[\s\p{P}]+/u).filter(Boolean);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { AuthProfileStore } from "../agents/auth-profiles.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
|
||||
|
||||
export const DEFAULT_LIVE_MUSIC_MODELS: Record<string, string> = {
|
||||
google: "google/lyria-3-clip-preview",
|
||||
@@ -24,8 +25,8 @@ export function parseCsvFilter(raw?: string): Set<string> | null {
|
||||
}
|
||||
const values = trimmed
|
||||
.split(",")
|
||||
.map((entry) => entry.trim().toLowerCase())
|
||||
.filter(Boolean);
|
||||
.map((entry) => normalizeOptionalLowercaseString(entry))
|
||||
.filter((entry): entry is string => Boolean(entry));
|
||||
return values.length > 0 ? new Set(values) : null;
|
||||
}
|
||||
|
||||
@@ -40,7 +41,11 @@ export function parseProviderModelMap(raw?: string): Map<string, string> {
|
||||
if (slash <= 0 || slash === trimmed.length - 1) {
|
||||
continue;
|
||||
}
|
||||
entries.set(trimmed.slice(0, slash).trim().toLowerCase(), trimmed);
|
||||
const providerId = normalizeOptionalLowercaseString(trimmed.slice(0, slash));
|
||||
if (!providerId) {
|
||||
continue;
|
||||
}
|
||||
entries.set(providerId, trimmed);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
@@ -57,7 +62,11 @@ export function resolveConfiguredLiveMusicModels(cfg: OpenClawConfig): Map<strin
|
||||
if (slash <= 0 || slash === trimmed.length - 1) {
|
||||
return;
|
||||
}
|
||||
resolved.set(trimmed.slice(0, slash).trim().toLowerCase(), trimmed);
|
||||
const providerId = normalizeOptionalLowercaseString(trimmed.slice(0, slash));
|
||||
if (!providerId) {
|
||||
return;
|
||||
}
|
||||
resolved.set(providerId, trimmed);
|
||||
};
|
||||
if (typeof configured === "string") {
|
||||
add(configured);
|
||||
|
||||
@@ -10,6 +10,7 @@ import { resolveStateDir, type OpenClawConfig } from "../config/config.js";
|
||||
import { coerceSecretRef } from "../config/types.secrets.js";
|
||||
import { resolveSecretInputRef, type SecretRef } from "../config/types.secrets.js";
|
||||
import { formatErrorMessage } from "../infra/errors.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import { resolveConfigDir, resolveUserPath } from "../utils.js";
|
||||
import { runTasksWithConcurrency } from "../utils/run-with-concurrency.js";
|
||||
import { iterateAuthProfileCredentials } from "./auth-profiles-scan.js";
|
||||
@@ -127,7 +128,7 @@ const SENSITIVE_MODEL_PROVIDER_HEADER_NAME_FRAGMENTS = [
|
||||
];
|
||||
|
||||
function isLikelySensitiveModelProviderHeaderName(value: string): boolean {
|
||||
const normalized = value.trim().toLowerCase();
|
||||
const normalized = normalizeLowercaseStringOrEmpty(value);
|
||||
if (!normalized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import type { AuthProfileStore } from "../agents/auth-profiles.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
} from "../shared/string-coerce.js";
|
||||
|
||||
export const DEFAULT_LIVE_VIDEO_MODELS: Record<string, string> = {
|
||||
alibaba: "alibaba/wan2.6-t2v",
|
||||
@@ -22,7 +26,7 @@ export function resolveLiveVideoResolution(params: {
|
||||
providerId: string;
|
||||
modelRef: string;
|
||||
}): "480P" | "768P" | "1080P" {
|
||||
const providerId = params.providerId.trim().toLowerCase();
|
||||
const providerId = normalizeLowercaseStringOrEmpty(params.providerId);
|
||||
if (providerId === "minimax") {
|
||||
return "768P";
|
||||
}
|
||||
@@ -47,8 +51,8 @@ export function parseCsvFilter(raw?: string): Set<string> | null {
|
||||
}
|
||||
const values = trimmed
|
||||
.split(",")
|
||||
.map((entry) => entry.trim().toLowerCase())
|
||||
.filter(Boolean);
|
||||
.map((entry) => normalizeOptionalLowercaseString(entry))
|
||||
.filter((entry): entry is string => Boolean(entry));
|
||||
return values.length > 0 ? new Set(values) : null;
|
||||
}
|
||||
|
||||
@@ -63,7 +67,11 @@ export function parseProviderModelMap(raw?: string): Map<string, string> {
|
||||
if (slash <= 0 || slash === trimmed.length - 1) {
|
||||
continue;
|
||||
}
|
||||
entries.set(trimmed.slice(0, slash).trim().toLowerCase(), trimmed);
|
||||
const providerId = normalizeOptionalLowercaseString(trimmed.slice(0, slash));
|
||||
if (!providerId) {
|
||||
continue;
|
||||
}
|
||||
entries.set(providerId, trimmed);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
@@ -80,7 +88,11 @@ export function resolveConfiguredLiveVideoModels(cfg: OpenClawConfig): Map<strin
|
||||
if (slash <= 0 || slash === trimmed.length - 1) {
|
||||
return;
|
||||
}
|
||||
resolved.set(trimmed.slice(0, slash).trim().toLowerCase(), trimmed);
|
||||
const providerId = normalizeOptionalLowercaseString(trimmed.slice(0, slash));
|
||||
if (!providerId) {
|
||||
return;
|
||||
}
|
||||
resolved.set(providerId, trimmed);
|
||||
};
|
||||
if (typeof configured === "string") {
|
||||
add(configured);
|
||||
@@ -97,7 +109,7 @@ export function canRunBufferBackedVideoToVideoLiveLane(params: {
|
||||
providerId: string;
|
||||
modelRef: string;
|
||||
}): boolean {
|
||||
const providerId = params.providerId.trim().toLowerCase();
|
||||
const providerId = normalizeLowercaseStringOrEmpty(params.providerId);
|
||||
if (REMOTE_URL_VIDEO_TO_VIDEO_PROVIDERS.has(providerId)) {
|
||||
return false;
|
||||
}
|
||||
@@ -116,7 +128,7 @@ export function canRunBufferBackedImageToVideoLiveLane(params: {
|
||||
providerId: string;
|
||||
modelRef: string;
|
||||
}): boolean {
|
||||
const providerId = params.providerId.trim().toLowerCase();
|
||||
const providerId = normalizeLowercaseStringOrEmpty(params.providerId);
|
||||
if (BUFFER_BACKED_IMAGE_TO_VIDEO_UNSUPPORTED_PROVIDERS.has(providerId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user