mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 13:11:40 +00:00
refactor: dedupe infra lowercase helpers
This commit is contained in:
@@ -8,6 +8,7 @@ import { Readable, Transform } from "node:stream";
|
||||
import { pipeline } from "node:stream/promises";
|
||||
import JSZip from "jszip";
|
||||
import * as tar from "tar";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import {
|
||||
resolveArchiveOutputPath,
|
||||
stripArchivePath,
|
||||
@@ -76,7 +77,7 @@ const OPEN_WRITE_CREATE_FLAGS =
|
||||
const TAR_SUFFIXES = [".tgz", ".tar.gz", ".tar"];
|
||||
|
||||
export function resolveArchiveKind(filePath: string): ArchiveKind | null {
|
||||
const lower = filePath.toLowerCase();
|
||||
const lower = normalizeLowercaseStringOrEmpty(filePath);
|
||||
if (lower.endsWith(".zip")) {
|
||||
return "zip";
|
||||
}
|
||||
|
||||
@@ -2,7 +2,10 @@ import { createHash } from "node:crypto";
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import { isAtLeast, parseSemver } from "./runtime-guard.js";
|
||||
import { compareComparableSemver, parseComparableSemver } from "./semver-compare.js";
|
||||
import { createTempDownloadTarget } from "./temp-download.js";
|
||||
@@ -415,7 +418,7 @@ export function parseClawHubPluginSpec(raw: string): {
|
||||
baseUrl?: string;
|
||||
} | null {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed.toLowerCase().startsWith("clawhub:")) {
|
||||
if (!normalizeLowercaseStringOrEmpty(trimmed).startsWith("clawhub:")) {
|
||||
return null;
|
||||
}
|
||||
const spec = trimmed.slice("clawhub:".length).trim();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import fs from "node:fs";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import { expandHomePrefix } from "./home-dir.js";
|
||||
|
||||
const GLOB_REGEX_CACHE_LIMIT = 512;
|
||||
@@ -7,7 +8,7 @@ const globRegexCache = new Map<string, RegExp>();
|
||||
function normalizeMatchTarget(value: string): string {
|
||||
if (process.platform === "win32") {
|
||||
const stripped = value.replace(/^\\\\[?.]\\/, "");
|
||||
return stripped.replace(/\\/g, "/").toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(stripped.replace(/\\/g, "/"));
|
||||
}
|
||||
return value.replace(/\\\\/g, "/");
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { DEFAULT_AGENT_ID } from "../routing/session-key.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
readStringValue,
|
||||
@@ -198,7 +199,7 @@ export function resolveExecApprovalsSocketPath(): string {
|
||||
|
||||
function normalizeAllowlistPattern(value: string | undefined): string | null {
|
||||
const trimmed = normalizeOptionalString(value) ?? "";
|
||||
return trimmed ? trimmed.toLowerCase() : null;
|
||||
return trimmed ? normalizeLowercaseStringOrEmpty(trimmed) : null;
|
||||
}
|
||||
|
||||
function mergeLegacyAgent(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import { expandHomePrefix } from "./home-dir.js";
|
||||
|
||||
export function isDriveLessWindowsRootedPath(value: string): boolean {
|
||||
@@ -50,7 +51,7 @@ function resolveWindowsExecutableExtensions(
|
||||
".EXE;.CMD;.BAT;.COM"
|
||||
)
|
||||
.split(";")
|
||||
.map((ext) => ext.toLowerCase()),
|
||||
.map((ext) => normalizeLowercaseStringOrEmpty(ext)),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -64,7 +65,7 @@ function resolveWindowsExecutableExtSet(env: NodeJS.ProcessEnv | undefined): Set
|
||||
".EXE;.CMD;.BAT;.COM"
|
||||
)
|
||||
.split(";")
|
||||
.map((ext) => ext.toLowerCase())
|
||||
.map((ext) => normalizeLowercaseStringOrEmpty(ext))
|
||||
.filter(Boolean),
|
||||
);
|
||||
}
|
||||
@@ -76,7 +77,7 @@ export function isExecutableFile(filePath: string): boolean {
|
||||
return false;
|
||||
}
|
||||
if (process.platform === "win32") {
|
||||
const ext = path.extname(filePath).toLowerCase();
|
||||
const ext = normalizeLowercaseStringOrEmpty(path.extname(filePath));
|
||||
if (!ext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
|
||||
function normalizeProcArg(arg: string): string {
|
||||
return arg.replaceAll("\\", "/").toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(arg.replaceAll("\\", "/"));
|
||||
}
|
||||
|
||||
export function parseProcCmdline(raw: string): string[] {
|
||||
|
||||
@@ -53,7 +53,7 @@ export function buildExecEventPrompt(opts?: { deliverToUser?: boolean }): string
|
||||
);
|
||||
}
|
||||
|
||||
const HEARTBEAT_OK_PREFIX = HEARTBEAT_TOKEN.toLowerCase();
|
||||
const HEARTBEAT_OK_PREFIX = normalizeLowercaseStringOrEmpty(HEARTBEAT_TOKEN);
|
||||
|
||||
// Detect heartbeat-specific noise so cron reminders don't trigger on non-reminder events.
|
||||
function isHeartbeatAckEvent(evt: string): boolean {
|
||||
@@ -61,7 +61,7 @@ function isHeartbeatAckEvent(evt: string): boolean {
|
||||
if (!trimmed) {
|
||||
return false;
|
||||
}
|
||||
const lower = trimmed.toLowerCase();
|
||||
const lower = normalizeLowercaseStringOrEmpty(trimmed);
|
||||
if (!lower.startsWith(HEARTBEAT_OK_PREFIX)) {
|
||||
return false;
|
||||
}
|
||||
@@ -85,7 +85,7 @@ function isHeartbeatNoiseEvent(evt: string): boolean {
|
||||
}
|
||||
|
||||
export function isExecCompletionEvent(evt: string): boolean {
|
||||
return evt.toLowerCase().includes("exec finished");
|
||||
return normalizeLowercaseStringOrEmpty(evt).includes("exec finished");
|
||||
}
|
||||
|
||||
// Returns true when a system event should be treated as real cron reminder content.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
|
||||
const CROSS_ORIGIN_REDIRECT_SAFE_HEADERS = new Set([
|
||||
"accept",
|
||||
"accept-encoding",
|
||||
@@ -23,7 +25,7 @@ export function retainSafeHeadersForCrossOriginRedirect(
|
||||
const incoming = new Headers(headers);
|
||||
const safeHeaders: Record<string, string> = {};
|
||||
for (const [key, value] of incoming.entries()) {
|
||||
if (CROSS_ORIGIN_REDIRECT_SAFE_HEADERS.has(key.toLowerCase())) {
|
||||
if (CROSS_ORIGIN_REDIRECT_SAFE_HEADERS.has(normalizeLowercaseStringOrEmpty(key))) {
|
||||
safeHeaders[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
|
||||
export function buildNodeShellCommand(command: string, platform?: string | null) {
|
||||
const normalized = String(platform ?? "")
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
const normalized = normalizeLowercaseStringOrEmpty(String(platform ?? "").trim());
|
||||
if (normalized.startsWith("win")) {
|
||||
return ["cmd.exe", "/d", "/s", "/c", command];
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
|
||||
const EXACT_SEMVER_VERSION_RE =
|
||||
/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z.-]+))?(?:\+([0-9A-Za-z.-]+))?$/;
|
||||
const DIST_TAG_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
||||
@@ -126,7 +128,7 @@ export function isPrereleaseResolutionAllowed(params: {
|
||||
if (params.spec.selectorKind === "exact-version") {
|
||||
return params.spec.selectorIsPrerelease;
|
||||
}
|
||||
return params.spec.selector?.toLowerCase() !== "latest";
|
||||
return normalizeLowercaseStringOrEmpty(params.spec.selector) !== "latest";
|
||||
}
|
||||
|
||||
export function formatPrereleaseResolutionError(params: {
|
||||
@@ -134,7 +136,8 @@ export function formatPrereleaseResolutionError(params: {
|
||||
resolvedVersion: string;
|
||||
}): string {
|
||||
const selectorHint =
|
||||
params.spec.selectorKind === "none" || params.spec.selector?.toLowerCase() === "latest"
|
||||
params.spec.selectorKind === "none" ||
|
||||
normalizeLowercaseStringOrEmpty(params.spec.selector) === "latest"
|
||||
? `Use "${params.spec.name}@beta" (or another prerelease tag) or an exact prerelease version to opt in explicitly.`
|
||||
: `Use an explicit prerelease tag or exact prerelease version if you want prerelease installs.`;
|
||||
return `Resolved ${params.spec.raw} to prerelease version ${params.resolvedVersion}, but prereleases are only installed when explicitly requested. ${selectorHint}`;
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../../shared/string-coerce.js";
|
||||
|
||||
function resolveExplicitConversationTargetId(target: string): string | undefined {
|
||||
for (const prefix of ["channel:", "conversation:", "group:", "room:", "dm:"]) {
|
||||
if (target.toLowerCase().startsWith(prefix)) {
|
||||
if (normalizeLowercaseStringOrEmpty(target).startsWith(prefix)) {
|
||||
return normalizeOptionalString(target.slice(prefix.length));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
} from "../../config/sessions/inbound.runtime.js";
|
||||
import { buildAgentSessionKey, type RoutePeer } from "../../routing/resolve-route.js";
|
||||
import { resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
import type { ResolvedMessagingTarget } from "./target-resolver.js";
|
||||
|
||||
export type OutboundSessionRoute = {
|
||||
@@ -39,8 +40,8 @@ function resolveOutboundChannelPlugin(channel: ChannelId) {
|
||||
|
||||
function stripProviderPrefix(raw: string, channel: string): string {
|
||||
const trimmed = raw.trim();
|
||||
const lower = trimmed.toLowerCase();
|
||||
const prefix = `${channel.toLowerCase()}:`;
|
||||
const lower = normalizeLowercaseStringOrEmpty(trimmed);
|
||||
const prefix = `${normalizeLowercaseStringOrEmpty(channel)}:`;
|
||||
if (lower.startsWith(prefix)) {
|
||||
return trimmed.slice(prefix.length).trim();
|
||||
}
|
||||
|
||||
@@ -31,7 +31,9 @@ function parseListenerAddress(address: string): { host: string; port: number } |
|
||||
const bracketMatch = normalized.match(/^\[([^\]]+)\]:(\d+)$/);
|
||||
if (bracketMatch) {
|
||||
const port = Number.parseInt(bracketMatch[2], 10);
|
||||
return Number.isFinite(port) ? { host: bracketMatch[1].toLowerCase(), port } : null;
|
||||
return Number.isFinite(port)
|
||||
? { host: normalizeLowercaseStringOrEmpty(bracketMatch[1]), port }
|
||||
: null;
|
||||
}
|
||||
const lastColon = normalized.lastIndexOf(":");
|
||||
if (lastColon <= 0 || lastColon >= normalized.length - 1) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { runCommandWithTimeout } from "../process/exec.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import { isErrno } from "./errors.js";
|
||||
import { buildPortHints } from "./ports-format.js";
|
||||
import { resolveLsofCommand } from "./ports-lsof.js";
|
||||
@@ -207,7 +208,7 @@ function parseNetstatListeners(output: string, port: number): PortListener[] {
|
||||
if (!line) {
|
||||
continue;
|
||||
}
|
||||
if (!line.toLowerCase().includes("listen")) {
|
||||
if (!normalizeLowercaseStringOrEmpty(line).includes("listen")) {
|
||||
continue;
|
||||
}
|
||||
if (!line.includes(portToken)) {
|
||||
@@ -239,7 +240,7 @@ async function resolveWindowsImageName(pid: number): Promise<string | undefined>
|
||||
}
|
||||
for (const rawLine of res.stdout.split(/\r?\n/)) {
|
||||
const line = rawLine.trim();
|
||||
if (!line.toLowerCase().startsWith("image name:")) {
|
||||
if (!normalizeLowercaseStringOrEmpty(line).startsWith("image name:")) {
|
||||
continue;
|
||||
}
|
||||
const value = line.slice("image name:".length).trim();
|
||||
@@ -263,7 +264,7 @@ async function resolveWindowsCommandLine(pid: number): Promise<string | undefine
|
||||
}
|
||||
for (const rawLine of res.stdout.split(/\r?\n/)) {
|
||||
const line = rawLine.trim();
|
||||
if (!line.toLowerCase().startsWith("commandline=")) {
|
||||
if (!normalizeLowercaseStringOrEmpty(line).startsWith("commandline=")) {
|
||||
continue;
|
||||
}
|
||||
const value = line.slice("commandline=".length).trim();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import { buildUsageHttpErrorSnapshot, fetchJson } from "./provider-usage.fetch.shared.js";
|
||||
import { clampPercent, PROVIDER_LABELS } from "./provider-usage.shared.js";
|
||||
import type {
|
||||
@@ -55,7 +56,7 @@ export async function fetchGeminiUsage(
|
||||
let hasFlash = false;
|
||||
|
||||
for (const [model, frac] of Object.entries(quotas)) {
|
||||
const lower = model.toLowerCase();
|
||||
const lower = normalizeLowercaseStringOrEmpty(model);
|
||||
if (lower.includes("pro")) {
|
||||
hasPro = true;
|
||||
if (frac < proMin) {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { URL } from "node:url";
|
||||
import type { GatewayConfig } from "../config/types.gateway.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import {
|
||||
loadOrCreateDeviceIdentity,
|
||||
signDevicePayload,
|
||||
@@ -70,7 +73,9 @@ function normalizeTimeoutMs(value: string | number | undefined): number {
|
||||
}
|
||||
|
||||
function readAllowHttp(value: string | undefined): boolean {
|
||||
const normalized = normalizeOptionalString(value)?.toLowerCase();
|
||||
const normalized = normalizeOptionalString(value)
|
||||
? normalizeLowercaseStringOrEmpty(value)
|
||||
: undefined;
|
||||
return normalized === "1" || normalized === "true" || normalized === "yes";
|
||||
}
|
||||
|
||||
|
||||
@@ -144,10 +144,7 @@ function isValidNodeId(value: string): boolean {
|
||||
}
|
||||
|
||||
function normalizeApnsToken(value: string): string {
|
||||
return value
|
||||
.trim()
|
||||
.replace(/[<>\s]/g, "")
|
||||
.toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(value.trim().replace(/[<>\s]/g, ""));
|
||||
}
|
||||
|
||||
function normalizeRelayHandle(value: string): string {
|
||||
@@ -187,10 +184,7 @@ function normalizeTokenDebugSuffix(value: unknown): string | undefined {
|
||||
if (typeof value !== "string") {
|
||||
return undefined;
|
||||
}
|
||||
const normalized = value
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/[^0-9a-z]/g, "");
|
||||
const normalized = normalizeLowercaseStringOrEmpty(value.trim()).replace(/[^0-9a-z]/g, "");
|
||||
return normalized.length > 0 ? normalized.slice(-8) : undefined;
|
||||
}
|
||||
|
||||
@@ -266,7 +260,9 @@ function normalizeDistribution(value: unknown): "official" | null {
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
}
|
||||
const normalized = normalizeOptionalString(value)?.toLowerCase();
|
||||
const normalized = normalizeOptionalString(value)
|
||||
? normalizeLowercaseStringOrEmpty(value)
|
||||
: undefined;
|
||||
return normalized === "official" ? "official" : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
|
||||
export const POSIX_INLINE_COMMAND_FLAGS = new Set(["-lc", "-c", "--command"]);
|
||||
export const POWERSHELL_INLINE_COMMAND_FLAGS = new Set([
|
||||
"-c",
|
||||
@@ -20,7 +22,7 @@ export function resolveInlineCommandMatch(
|
||||
if (!token) {
|
||||
continue;
|
||||
}
|
||||
const lower = token.toLowerCase();
|
||||
const lower = normalizeLowercaseStringOrEmpty(token);
|
||||
if (lower === "--") {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,10 @@ import { promptYesNo } from "../cli/prompt.js";
|
||||
import { danger, info, logVerbose, shouldLogVerbose, warn } from "../globals.js";
|
||||
import { runExec } from "../process/exec.js";
|
||||
import { defaultRuntime, type RuntimeEnv } from "../runtime.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import { colorize, isRich, theme } from "../terminal/theme.js";
|
||||
import { ensureBinary } from "./binaries.js";
|
||||
|
||||
@@ -272,7 +275,7 @@ function isPermissionDeniedError(err: unknown): boolean {
|
||||
if (code.toUpperCase() === "EACCES") {
|
||||
return true;
|
||||
}
|
||||
const combined = `${stdout}\n${stderr}\n${message}`.toLowerCase();
|
||||
const combined = normalizeLowercaseStringOrEmpty(`${stdout}\n${stderr}\n${message}`);
|
||||
return (
|
||||
combined.includes("permission denied") ||
|
||||
combined.includes("access denied") ||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js";
|
||||
|
||||
export function normalizeFingerprint(input: string): string {
|
||||
const trimmed = input.trim();
|
||||
const withoutPrefix = trimmed.replace(/^sha-?256\s*:?\s*/i, "");
|
||||
return withoutPrefix.replace(/[^a-fA-F0-9]/g, "").toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(withoutPrefix.replace(/[^a-fA-F0-9]/g, ""));
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { BUNDLED_RUNTIME_SIDECAR_PATHS } from "../plugins/runtime-sidecar-paths.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import { pathExists } from "../utils.js";
|
||||
import { readPackageVersion } from "./package-json.js";
|
||||
import { applyPathPrepend } from "./path-prepend.js";
|
||||
@@ -39,7 +40,7 @@ function normalizePackageTarget(value: string): string {
|
||||
}
|
||||
|
||||
export function isMainPackageTarget(value: string): boolean {
|
||||
return normalizePackageTarget(value).toLowerCase() === "main";
|
||||
return normalizeLowercaseStringOrEmpty(normalizePackageTarget(value)) === "main";
|
||||
}
|
||||
|
||||
export function isExplicitPackageInstallSpec(value: string): boolean {
|
||||
@@ -205,7 +206,10 @@ function inferNpmPrefixFromPackageRoot(pkgRoot?: string | null): string | null {
|
||||
if (path.basename(parentDir) === "lib") {
|
||||
return path.dirname(parentDir);
|
||||
}
|
||||
if (process.platform === "win32" && path.basename(parentDir).toLowerCase() === "npm") {
|
||||
if (
|
||||
process.platform === "win32" &&
|
||||
normalizeLowercaseStringOrEmpty(path.basename(parentDir)) === "npm"
|
||||
) {
|
||||
return parentDir;
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -5,6 +5,7 @@ import { formatCliCommand } from "../cli/command-format.js";
|
||||
import type { loadConfig } from "../config/config.js";
|
||||
import { resolveStateDir } from "../config/paths.js";
|
||||
import { runCommandWithTimeout } from "../process/exec.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import { VERSION } from "../version.js";
|
||||
import { writeJsonAtomic } from "./json-files.js";
|
||||
import { resolveOpenClawPackageRoot } from "./openclaw-root.js";
|
||||
@@ -236,7 +237,7 @@ async function runAutoUpdateCommand(params: {
|
||||
const baseArgs = ["update", "--yes", "--channel", params.channel, "--json"];
|
||||
const execPath = process.execPath?.trim();
|
||||
const argv1 = process.argv[1]?.trim();
|
||||
const lowerExecBase = execPath ? path.basename(execPath).toLowerCase() : "";
|
||||
const lowerExecBase = execPath ? normalizeLowercaseStringOrEmpty(path.basename(execPath)) : "";
|
||||
const runtimeIsNodeOrBun =
|
||||
lowerExecBase === "node" ||
|
||||
lowerExecBase === "node.exe" ||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { parseCmdScriptCommandLine } from "../daemon/cmd-argv.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
|
||||
const DEFAULT_TIMEOUT_MS = 5_000;
|
||||
|
||||
@@ -95,13 +96,13 @@ function extractWindowsCommandLine(raw: string): string | null {
|
||||
.map((line) => line.trim())
|
||||
.filter(Boolean);
|
||||
for (const line of lines) {
|
||||
if (!line.toLowerCase().startsWith("commandline=")) {
|
||||
if (!normalizeLowercaseStringOrEmpty(line).startsWith("commandline=")) {
|
||||
continue;
|
||||
}
|
||||
const value = line.slice("commandline=".length).trim();
|
||||
return value || null;
|
||||
}
|
||||
return lines.find((line) => line.toLowerCase() !== "commandline") ?? null;
|
||||
return lines.find((line) => normalizeLowercaseStringOrEmpty(line) !== "commandline") ?? null;
|
||||
}
|
||||
|
||||
export function readWindowsProcessArgsSync(
|
||||
|
||||
Reference in New Issue
Block a user