mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 01:31:08 +00:00
refactor: dedupe misc lowercase helpers
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
type Event,
|
||||
} from "nostr-tools";
|
||||
import { decrypt, encrypt } from "nostr-tools/nip04";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
createDirectDmPreCryptoGuardPolicy,
|
||||
type DirectDmPreCryptoGuardPolicyOverrides,
|
||||
@@ -877,7 +878,7 @@ export function normalizePubkey(input: string): string {
|
||||
if (!/^[0-9a-fA-F]{64}$/.test(trimmed)) {
|
||||
throw new Error("Pubkey must be 64 hex characters or npub format");
|
||||
}
|
||||
return trimmed.toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(trimmed);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
readStringValue,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
@@ -114,7 +115,7 @@ function validateUrlSafety(urlStr: string): { ok: true } | { ok: false; error: s
|
||||
return { ok: false, error: "URL must use https:// protocol" };
|
||||
}
|
||||
|
||||
const hostname = url.hostname.toLowerCase();
|
||||
const hostname = normalizeLowercaseStringOrEmpty(url.hostname);
|
||||
|
||||
if (isBlockedHostnameOrIp(hostname)) {
|
||||
return { ok: false, error: "URL must not point to private/internal addresses" };
|
||||
@@ -197,7 +198,7 @@ function isLoopbackRemoteAddress(remoteAddress: string | undefined): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ipLower = remoteAddress.toLowerCase().replace(/^\[|\]$/g, "");
|
||||
const ipLower = normalizeLowercaseStringOrEmpty(remoteAddress).replace(/^\[|\]$/g, "");
|
||||
|
||||
// IPv6 loopback
|
||||
if (ipLower === "::1") {
|
||||
@@ -221,7 +222,7 @@ function isLoopbackRemoteAddress(remoteAddress: string | undefined): boolean {
|
||||
function isLoopbackOriginLike(value: string): boolean {
|
||||
try {
|
||||
const url = new URL(value);
|
||||
const hostname = url.hostname.toLowerCase();
|
||||
const hostname = normalizeLowercaseStringOrEmpty(url.hostname);
|
||||
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1";
|
||||
} catch {
|
||||
return false;
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
runSshSandboxCommand,
|
||||
sanitizeEnvVars,
|
||||
} from "openclaw/plugin-sdk/sandbox";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
buildExecRemoteCommand,
|
||||
buildRemoteCommand,
|
||||
@@ -504,8 +505,7 @@ function resolveOpenShellPluginConfigFromConfig(
|
||||
|
||||
function buildOpenShellSandboxName(scopeKey: string): string {
|
||||
const trimmed = scopeKey.trim() || "session";
|
||||
const safe = trimmed
|
||||
.toLowerCase()
|
||||
const safe = normalizeLowercaseStringOrEmpty(trimmed)
|
||||
.replace(/[^a-z0-9._-]+/g, "-")
|
||||
.replace(/^-+|-+$/g, "")
|
||||
.slice(0, 32);
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
|
||||
export const DEFAULT_OPEN_SHELL_MIRROR_EXCLUDE_DIRS = ["hooks", "git-hooks", ".git"] as const;
|
||||
const COPY_TREE_FS_CONCURRENCY = 16;
|
||||
|
||||
function createExcludeMatcher(excludeDirs?: readonly string[]) {
|
||||
const excluded = new Set((excludeDirs ?? []).map((d) => d.toLowerCase()));
|
||||
return (name: string) => excluded.has(name.toLowerCase());
|
||||
const excluded = new Set((excludeDirs ?? []).map((d) => normalizeLowercaseStringOrEmpty(d)));
|
||||
return (name: string) => excluded.has(normalizeLowercaseStringOrEmpty(name));
|
||||
}
|
||||
|
||||
function createConcurrencyLimiter(limit: number) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
definePluginEntry,
|
||||
@@ -260,7 +260,7 @@ function formatHelp(): string {
|
||||
}
|
||||
|
||||
function parseGroup(raw: string | undefined): ArmGroup | null {
|
||||
const value = normalizeOptionalString(raw)?.toLowerCase() ?? "";
|
||||
const value = normalizeOptionalLowercaseString(raw) ?? "";
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
@@ -354,7 +354,7 @@ export default definePluginEntry({
|
||||
handler: async (ctx) => {
|
||||
const args = ctx.args?.trim() ?? "";
|
||||
const tokens = args.split(/\s+/).filter(Boolean);
|
||||
const action = tokens[0]?.toLowerCase() ?? "";
|
||||
const action = normalizeLowercaseStringOrEmpty(tokens[0]);
|
||||
|
||||
const stateDir = api.runtime.state.resolveStateDir();
|
||||
const statePath = resolveStatePath(stateDir);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import * as querystring from "node:querystring";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
beginWebhookRequestPipelineOrReject,
|
||||
createWebhookInFlightLimiter,
|
||||
@@ -264,7 +265,7 @@ function extractTokenFromHeaders(req: IncomingMessage): string | undefined {
|
||||
* - text <- text | message | content
|
||||
*/
|
||||
function parsePayload(req: IncomingMessage, body: string): SynologyWebhookPayload | null {
|
||||
const contentType = String(req.headers["content-type"] ?? "").toLowerCase();
|
||||
const contentType = normalizeLowercaseStringOrEmpty(req.headers["content-type"]);
|
||||
|
||||
let bodyFields: Record<string, unknown> = {};
|
||||
if (contentType.includes("application/json")) {
|
||||
|
||||
@@ -156,24 +156,24 @@ function resolveZalouserInboundSessionKey(params: {
|
||||
return params.route.sessionKey;
|
||||
}
|
||||
|
||||
const directSessionKey = params.core.channel.routing
|
||||
.buildAgentSessionKey({
|
||||
const directSessionKey = normalizeLowercaseStringOrEmpty(
|
||||
params.core.channel.routing.buildAgentSessionKey({
|
||||
agentId: params.route.agentId,
|
||||
channel: "zalouser",
|
||||
accountId: params.route.accountId,
|
||||
peer: { kind: "direct", id: params.senderId },
|
||||
dmScope: resolveZalouserDmSessionScope(params.config),
|
||||
identityLinks: params.config.session?.identityLinks,
|
||||
})
|
||||
.toLowerCase();
|
||||
const legacySessionKey = params.core.channel.routing
|
||||
.buildAgentSessionKey({
|
||||
}),
|
||||
);
|
||||
const legacySessionKey = normalizeLowercaseStringOrEmpty(
|
||||
params.core.channel.routing.buildAgentSessionKey({
|
||||
agentId: params.route.agentId,
|
||||
channel: "zalouser",
|
||||
accountId: params.route.accountId,
|
||||
peer: { kind: "group", id: params.senderId },
|
||||
})
|
||||
.toLowerCase();
|
||||
}),
|
||||
);
|
||||
const hasDirectSession =
|
||||
params.core.channel.session.readSessionUpdatedAt({
|
||||
storePath: params.storePath,
|
||||
@@ -844,7 +844,7 @@ export async function monitorZalouserProvider(
|
||||
mapping.push(`${entry}→${cleaned}`);
|
||||
continue;
|
||||
}
|
||||
const matches = byName.get(cleaned.toLowerCase()) ?? [];
|
||||
const matches = byName.get(normalizeLowercaseStringOrEmpty(cleaned)) ?? [];
|
||||
const match = matches[0];
|
||||
const id = match?.groupId ? String(match.groupId) : undefined;
|
||||
if (id) {
|
||||
|
||||
@@ -17,7 +17,7 @@ export function applyDirectoryQueryAndLimit(
|
||||
): string[] {
|
||||
const q = resolveDirectoryQuery(params.query);
|
||||
const limit = resolveDirectoryLimit(params.limit);
|
||||
const filtered = ids.filter((id) => (q ? id.toLowerCase().includes(q) : true));
|
||||
const filtered = ids.filter((id) => (q ? normalizeLowercaseStringOrEmpty(id).includes(q) : true));
|
||||
return typeof limit === "number" ? filtered.slice(0, limit) : filtered;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
import {
|
||||
type ChannelId,
|
||||
getChannelPlugin,
|
||||
@@ -29,20 +30,18 @@ export function requirePairingAdapter(channelId: ChannelId): ChannelPairingAdapt
|
||||
}
|
||||
|
||||
export function resolvePairingChannel(raw: unknown): ChannelId {
|
||||
const value = (
|
||||
const value =
|
||||
typeof raw === "string"
|
||||
? raw
|
||||
: typeof raw === "number" || typeof raw === "boolean"
|
||||
? String(raw)
|
||||
: ""
|
||||
)
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
const normalized = normalizeChannelId(value);
|
||||
: "";
|
||||
const normalizedValue = normalizeLowercaseStringOrEmpty(value);
|
||||
const normalized = normalizeChannelId(normalizedValue);
|
||||
const channels = listPairingChannels();
|
||||
if (!normalized || !channels.includes(normalized)) {
|
||||
throw new Error(
|
||||
`Invalid channel: ${value || "(empty)"} (expected one of: ${channels.join(", ")})`,
|
||||
`Invalid channel: ${normalizedValue || "(empty)"} (expected one of: ${channels.join(", ")})`,
|
||||
);
|
||||
}
|
||||
return normalized;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
|
||||
export type ToolContentBlock = Record<string, unknown>;
|
||||
|
||||
export function normalizeToolContentType(value: unknown): string {
|
||||
return typeof value === "string" ? value.toLowerCase() : "";
|
||||
return normalizeLowercaseStringOrEmpty(value);
|
||||
}
|
||||
|
||||
export function isToolCallContentType(value: unknown): boolean {
|
||||
|
||||
@@ -351,7 +351,7 @@ function filterRunLogEntries(
|
||||
if (!opts.query) {
|
||||
return true;
|
||||
}
|
||||
return opts.queryTextForEntry(entry).toLowerCase().includes(opts.query);
|
||||
return normalizeLowercaseStringOrEmpty(opts.queryTextForEntry(entry)).includes(opts.query);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,10 @@ import type {
|
||||
PluginHookMessageReceivedEvent,
|
||||
PluginHookMessageSentEvent,
|
||||
} from "../plugins/types.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import type {
|
||||
MessagePreprocessedHookContext,
|
||||
MessageReceivedHookContext,
|
||||
@@ -76,7 +79,9 @@ export function deriveInboundMessageHookContext(
|
||||
: typeof ctx.Body === "string"
|
||||
? ctx.Body
|
||||
: "");
|
||||
const channelId = (ctx.OriginatingChannel ?? ctx.Surface ?? ctx.Provider ?? "").toLowerCase();
|
||||
const channelId = normalizeLowercaseStringOrEmpty(
|
||||
ctx.OriginatingChannel ?? ctx.Surface ?? ctx.Provider ?? "",
|
||||
);
|
||||
const conversationId = ctx.OriginatingTo ?? ctx.To ?? ctx.From ?? undefined;
|
||||
const isGroup = Boolean(ctx.GroupSubject || ctx.GroupChannel);
|
||||
const mediaPaths = Array.isArray(ctx.MediaPaths)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import type { ChannelApprovalKind } from "../channels/plugins/types.adapters.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import type {
|
||||
ChannelApprovalNativeDeliveryPlan,
|
||||
ChannelApprovalNativePlannedTarget,
|
||||
@@ -61,7 +64,7 @@ let approvalRouteRuntimeSeq = 0;
|
||||
const MAX_APPROVAL_ROUTE_NOTICE_TTL_MS = 5 * 60_000;
|
||||
|
||||
function normalizeChannel(value?: string | null): string {
|
||||
return value?.trim().toLowerCase() || "";
|
||||
return normalizeLowercaseStringOrEmpty(value);
|
||||
}
|
||||
|
||||
function clearPendingApprovalRouteNotice(approvalId: string): void {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
|
||||
|
||||
export type ParsedLogLine = {
|
||||
time?: string;
|
||||
level?: string;
|
||||
@@ -51,7 +53,7 @@ export function parseLogLine(raw: string): ParsedLogLine | null {
|
||||
: typeof meta?.date === "string"
|
||||
? meta.date
|
||||
: undefined,
|
||||
level: levelRaw ? levelRaw.toLowerCase() : undefined,
|
||||
level: normalizeOptionalLowercaseString(levelRaw),
|
||||
subsystem: nameMeta.subsystem,
|
||||
module: nameMeta.module,
|
||||
message: extractMessage(parsed),
|
||||
|
||||
@@ -10,7 +10,10 @@ import {
|
||||
resolveInputFileLimits,
|
||||
} from "../media/input-files.js";
|
||||
import { wrapExternalContent } from "../security/external-content.js";
|
||||
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import { resolveAttachmentKind } from "./attachments.js";
|
||||
import { runWithConcurrency } from "./concurrency.js";
|
||||
import { DEFAULT_ECHO_TRANSCRIPT_FORMAT, sendTranscriptEcho } from "./echo-transcript.js";
|
||||
@@ -285,7 +288,7 @@ function resolveTextMimeFromName(name?: string): string | undefined {
|
||||
if (!name) {
|
||||
return undefined;
|
||||
}
|
||||
const ext = path.extname(name).toLowerCase();
|
||||
const ext = normalizeLowercaseStringOrEmpty(path.extname(name));
|
||||
return TEXT_EXT_MIME.get(ext);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import { resolveProxyFetchFromEnv } from "../infra/net/proxy-fetch.js";
|
||||
import { resolvePreferredOpenClawTmpDir } from "../infra/tmp-openclaw-dir.js";
|
||||
import { runFfmpeg } from "../media/ffmpeg-exec.js";
|
||||
import { runExec } from "../process/exec.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import { MediaAttachmentCache } from "./attachments.js";
|
||||
import {
|
||||
CLI_OUTPUT_MAX_BUFFER,
|
||||
@@ -226,7 +227,7 @@ async function resolveCliMediaPath(params: {
|
||||
return params.mediaPath;
|
||||
}
|
||||
|
||||
const ext = path.extname(params.mediaPath).toLowerCase();
|
||||
const ext = normalizeLowercaseStringOrEmpty(path.extname(params.mediaPath));
|
||||
if (ext === ".wav") {
|
||||
return params.mediaPath;
|
||||
}
|
||||
|
||||
@@ -297,7 +297,9 @@ async function probeGeminiCli(): Promise<boolean> {
|
||||
const { stdout } = await runExec("gemini", ["--output-format", "json", "ok"], {
|
||||
timeoutMs: 8000,
|
||||
});
|
||||
return Boolean(extractGeminiResponse(stdout) ?? stdout.toLowerCase().includes("ok"));
|
||||
return Boolean(
|
||||
extractGeminiResponse(stdout) ?? normalizeLowercaseStringOrEmpty(stdout).includes("ok"),
|
||||
);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,10 @@ import {
|
||||
isRfc1918Ipv4Address,
|
||||
parseCanonicalIpAddress,
|
||||
} from "../shared/net/ip.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import { resolveTailnetHostWithRunner } from "../shared/tailscale-status.js";
|
||||
|
||||
export type PairingSetupPayload = {
|
||||
@@ -101,7 +104,7 @@ function isPrivateLanIpHost(host: string): boolean {
|
||||
if (!isIpv6Address(parsed)) {
|
||||
return false;
|
||||
}
|
||||
const normalized = parsed.toString().toLowerCase();
|
||||
const normalized = normalizeLowercaseStringOrEmpty(parsed.toString());
|
||||
return (
|
||||
normalized.startsWith("fe80:") || normalized.startsWith("fc") || normalized.startsWith("fd")
|
||||
);
|
||||
|
||||
@@ -678,18 +678,22 @@ export function resolveAgentRoute(input: ResolveAgentRouteInput): ResolvedAgentR
|
||||
|
||||
const choose = (agentId: string, matchedBy: ResolvedAgentRoute["matchedBy"]) => {
|
||||
const resolvedAgentId = pickFirstExistingAgentId(input.cfg, agentId);
|
||||
const sessionKey = buildAgentSessionKey({
|
||||
agentId: resolvedAgentId,
|
||||
channel,
|
||||
accountId,
|
||||
peer,
|
||||
dmScope,
|
||||
identityLinks,
|
||||
}).toLowerCase();
|
||||
const mainSessionKey = buildAgentMainSessionKey({
|
||||
agentId: resolvedAgentId,
|
||||
mainKey: DEFAULT_MAIN_KEY,
|
||||
}).toLowerCase();
|
||||
const sessionKey = normalizeLowercaseStringOrEmpty(
|
||||
buildAgentSessionKey({
|
||||
agentId: resolvedAgentId,
|
||||
channel,
|
||||
accountId,
|
||||
peer,
|
||||
dmScope,
|
||||
identityLinks,
|
||||
}),
|
||||
);
|
||||
const mainSessionKey = normalizeLowercaseStringOrEmpty(
|
||||
buildAgentMainSessionKey({
|
||||
agentId: resolvedAgentId,
|
||||
mainKey: DEFAULT_MAIN_KEY,
|
||||
}),
|
||||
);
|
||||
const route = {
|
||||
agentId: resolvedAgentId,
|
||||
channel,
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { normalizeChatType } from "../channels/chat-type.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { SessionChatType, SessionEntry } from "../config/sessions.js";
|
||||
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
} from "../shared/string-coerce.js";
|
||||
|
||||
export type SessionSendPolicyDecision = "allow" | "deny";
|
||||
|
||||
@@ -102,8 +105,8 @@ export function resolveSendPolicy(params: {
|
||||
normalizeChatType(deriveChatTypeFromKey(params.sessionKey));
|
||||
const rawSessionKey = params.sessionKey ?? "";
|
||||
const strippedSessionKey = stripAgentSessionKeyPrefix(rawSessionKey) ?? "";
|
||||
const rawSessionKeyNorm = rawSessionKey.toLowerCase();
|
||||
const strippedSessionKeyNorm = strippedSessionKey.toLowerCase();
|
||||
const rawSessionKeyNorm = normalizeLowercaseStringOrEmpty(rawSessionKey);
|
||||
const strippedSessionKeyNorm = normalizeLowercaseStringOrEmpty(strippedSessionKey);
|
||||
|
||||
let allowedMatch = false;
|
||||
for (const rule of policy.rules ?? []) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { isCronJobActive } from "../cron/active-jobs.js";
|
||||
import { getAgentRunContext } from "../infra/agent-events.js";
|
||||
import { parseAgentSessionKey } from "../routing/session-key.js";
|
||||
import { deriveSessionChatType } from "../sessions/session-chat-type.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import {
|
||||
deleteTaskRecordById,
|
||||
ensureTaskRegistryReady,
|
||||
@@ -81,9 +82,9 @@ function findSessionEntryByKey(store: Record<string, unknown>, sessionKey: strin
|
||||
if (direct) {
|
||||
return direct;
|
||||
}
|
||||
const normalized = sessionKey.toLowerCase();
|
||||
const normalized = normalizeLowercaseStringOrEmpty(sessionKey);
|
||||
for (const [key, entry] of Object.entries(store)) {
|
||||
if (key.toLowerCase() === normalized) {
|
||||
if (normalizeLowercaseStringOrEmpty(key) === normalized) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ export function parseTtsDirectives(
|
||||
if (!rawKey || !rawValue) {
|
||||
continue;
|
||||
}
|
||||
const key = rawKey.toLowerCase();
|
||||
const key = normalizeLowercaseStringOrEmpty(rawKey);
|
||||
if (key === "provider") {
|
||||
if (policy.allowProvider) {
|
||||
const providerId = normalizeLowercaseStringOrEmpty(rawValue);
|
||||
|
||||
@@ -10,7 +10,10 @@ import {
|
||||
import { resolveModelAsync } from "../agents/pi-embedded-runner/model.js";
|
||||
import { prepareModelForSimpleCompletion } from "../agents/simple-completion-transport.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import type { ResolvedTtsConfig } from "./tts.js";
|
||||
|
||||
const TEMP_FILE_CLEANUP_DELAY_MS = 5 * 60 * 1000; // 5 minutes
|
||||
@@ -40,11 +43,10 @@ export function requireInRange(value: number, min: number, max: number, label: s
|
||||
}
|
||||
|
||||
export function normalizeLanguageCode(code?: string): string | undefined {
|
||||
const trimmed = normalizeOptionalString(code);
|
||||
if (!trimmed) {
|
||||
const normalized = normalizeOptionalLowercaseString(code);
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
const normalized = trimmed.toLowerCase();
|
||||
if (!/^[a-z]{2}$/.test(normalized)) {
|
||||
throw new Error("languageCode must be a 2-letter ISO 639-1 code (e.g. en, de, fr)");
|
||||
}
|
||||
@@ -52,11 +54,10 @@ export function normalizeLanguageCode(code?: string): string | undefined {
|
||||
}
|
||||
|
||||
export function normalizeApplyTextNormalization(mode?: string): "auto" | "on" | "off" | undefined {
|
||||
const trimmed = normalizeOptionalString(mode);
|
||||
if (!trimmed) {
|
||||
const normalized = normalizeOptionalLowercaseString(mode);
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
const normalized = trimmed.toLowerCase();
|
||||
if (normalized === "auto" || normalized === "on" || normalized === "off") {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { assertOkOrThrowHttpError, fetchWithTimeout } from "openclaw/plugin-sdk/provider-http";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import type {
|
||||
GeneratedVideoAsset,
|
||||
VideoGenerationRequest,
|
||||
@@ -139,7 +140,7 @@ export async function pollDashscopeVideoTaskUntilComplete(params: {
|
||||
throw new Error(
|
||||
payload.output?.message?.trim() ||
|
||||
payload.message?.trim() ||
|
||||
`${params.providerLabel} video generation task ${params.taskId} ${status.toLowerCase()}`,
|
||||
`${params.providerLabel} video generation task ${params.taskId} ${normalizeLowercaseStringOrEmpty(status)}`,
|
||||
);
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, DEFAULT_VIDEO_GENERATION_POLL_INTERVAL_MS));
|
||||
|
||||
@@ -9,7 +9,10 @@ import { resolveRuntimeWebSearchProviders } from "../plugins/web-search-provider
|
||||
import { sortWebSearchProvidersForAutoDetect } from "../plugins/web-search-providers.shared.js";
|
||||
import { getActiveRuntimeWebToolsMetadata } from "../secrets/runtime-web-tools-state.js";
|
||||
import type { RuntimeWebSearchMetadata } from "../secrets/runtime-web-tools.types.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import {
|
||||
hasWebProviderEntryCredential,
|
||||
providerRequiresCredential,
|
||||
@@ -280,11 +283,9 @@ function hasExplicitWebSearchSelection(params: {
|
||||
if (configuredProviderId && availableProviderIds.has(configuredProviderId)) {
|
||||
return true;
|
||||
}
|
||||
const runtimeConfiguredId = (
|
||||
params.runtimeWebSearch?.selectedProvider ?? params.runtimeWebSearch?.providerConfigured
|
||||
)
|
||||
?.trim()
|
||||
.toLowerCase();
|
||||
const runtimeConfiguredId = normalizeOptionalLowercaseString(
|
||||
params.runtimeWebSearch?.selectedProvider ?? params.runtimeWebSearch?.providerConfigured,
|
||||
);
|
||||
if (
|
||||
params.runtimeWebSearch?.providerSource === "configured" &&
|
||||
runtimeConfiguredId &&
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
text,
|
||||
} from "@clack/prompts";
|
||||
import { createCliProgress } from "../cli/progress.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import { stripAnsi } from "../terminal/ansi.js";
|
||||
import { note as emitNote } from "../terminal/note.js";
|
||||
import { stylePromptHint, stylePromptMessage, stylePromptTitle } from "../terminal/prompt-style.js";
|
||||
@@ -28,8 +29,7 @@ function guardCancel<T>(value: T | symbol): T {
|
||||
}
|
||||
|
||||
function normalizeSearchTokens(search: string): string[] {
|
||||
return search
|
||||
.toLowerCase()
|
||||
return normalizeLowercaseStringOrEmpty(search)
|
||||
.split(/\s+/)
|
||||
.map((token) => token.trim())
|
||||
.filter((token) => token.length > 0);
|
||||
@@ -39,7 +39,7 @@ function buildOptionSearchText<T>(option: Option<T>): string {
|
||||
const label = stripAnsi(option.label ?? "");
|
||||
const hint = stripAnsi(option.hint ?? "");
|
||||
const value = String(option.value ?? "");
|
||||
return `${label} ${hint} ${value}`.toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(`${label} ${hint} ${value}`);
|
||||
}
|
||||
|
||||
export function tokenizedOptionFilter<T>(search: string, option: Option<T>): boolean {
|
||||
|
||||
Reference in New Issue
Block a user