mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-02 21:50:20 +00:00
chore: Enable "curly" rule to avoid single-statement if confusion/errors.
This commit is contained in:
@@ -199,16 +199,22 @@ class SkillBinsCache {
|
||||
function sanitizeEnv(
|
||||
overrides?: Record<string, string> | null,
|
||||
): Record<string, string> | undefined {
|
||||
if (!overrides) return undefined;
|
||||
if (!overrides) {
|
||||
return undefined;
|
||||
}
|
||||
const merged = { ...process.env } as Record<string, string>;
|
||||
const basePath = process.env.PATH ?? DEFAULT_NODE_PATH;
|
||||
for (const [rawKey, value] of Object.entries(overrides)) {
|
||||
const key = rawKey.trim();
|
||||
if (!key) continue;
|
||||
if (!key) {
|
||||
continue;
|
||||
}
|
||||
const upper = key.toUpperCase();
|
||||
if (upper === "PATH") {
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) continue;
|
||||
if (!trimmed) {
|
||||
continue;
|
||||
}
|
||||
if (!basePath || trimmed === basePath) {
|
||||
merged[key] = trimmed;
|
||||
continue;
|
||||
@@ -219,8 +225,12 @@ function sanitizeEnv(
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (blockedEnvKeys.has(upper)) continue;
|
||||
if (blockedEnvPrefixes.some((prefix) => upper.startsWith(prefix))) continue;
|
||||
if (blockedEnvKeys.has(upper)) {
|
||||
continue;
|
||||
}
|
||||
if (blockedEnvPrefixes.some((prefix) => upper.startsWith(prefix))) {
|
||||
continue;
|
||||
}
|
||||
merged[key] = value;
|
||||
}
|
||||
return merged;
|
||||
@@ -241,7 +251,9 @@ function resolveBrowserProxyConfig() {
|
||||
let browserControlReady: Promise<void> | null = null;
|
||||
|
||||
async function ensureBrowserControlService(): Promise<void> {
|
||||
if (browserControlReady) return browserControlReady;
|
||||
if (browserControlReady) {
|
||||
return browserControlReady;
|
||||
}
|
||||
browserControlReady = (async () => {
|
||||
const cfg = loadConfig();
|
||||
const resolved = resolveBrowserConfig(cfg.browser, cfg);
|
||||
@@ -249,7 +261,9 @@ async function ensureBrowserControlService(): Promise<void> {
|
||||
throw new Error("browser control disabled");
|
||||
}
|
||||
const started = await startBrowserControlServiceFromConfig();
|
||||
if (!started) throw new Error("browser control disabled");
|
||||
if (!started) {
|
||||
throw new Error("browser control disabled");
|
||||
}
|
||||
})();
|
||||
return browserControlReady;
|
||||
}
|
||||
@@ -259,7 +273,9 @@ async function withTimeout<T>(promise: Promise<T>, timeoutMs?: number, label?: s
|
||||
typeof timeoutMs === "number" && Number.isFinite(timeoutMs)
|
||||
? Math.max(1, Math.floor(timeoutMs))
|
||||
: undefined;
|
||||
if (!resolved) return await promise;
|
||||
if (!resolved) {
|
||||
return await promise;
|
||||
}
|
||||
let timer: ReturnType<typeof setTimeout> | undefined;
|
||||
const timeoutPromise = new Promise<never>((_, reject) => {
|
||||
timer = setTimeout(() => {
|
||||
@@ -269,14 +285,20 @@ async function withTimeout<T>(promise: Promise<T>, timeoutMs?: number, label?: s
|
||||
try {
|
||||
return await Promise.race([promise, timeoutPromise]);
|
||||
} finally {
|
||||
if (timer) clearTimeout(timer);
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isProfileAllowed(params: { allowProfiles: string[]; profile?: string | null }) {
|
||||
const { allowProfiles, profile } = params;
|
||||
if (!allowProfiles.length) return true;
|
||||
if (!profile) return false;
|
||||
if (!allowProfiles.length) {
|
||||
return true;
|
||||
}
|
||||
if (!profile) {
|
||||
return false;
|
||||
}
|
||||
return allowProfiles.includes(profile.trim());
|
||||
}
|
||||
|
||||
@@ -284,20 +306,30 @@ function collectBrowserProxyPaths(payload: unknown): string[] {
|
||||
const paths = new Set<string>();
|
||||
const obj =
|
||||
typeof payload === "object" && payload !== null ? (payload as Record<string, unknown>) : null;
|
||||
if (!obj) return [];
|
||||
if (typeof obj.path === "string" && obj.path.trim()) paths.add(obj.path.trim());
|
||||
if (typeof obj.imagePath === "string" && obj.imagePath.trim()) paths.add(obj.imagePath.trim());
|
||||
if (!obj) {
|
||||
return [];
|
||||
}
|
||||
if (typeof obj.path === "string" && obj.path.trim()) {
|
||||
paths.add(obj.path.trim());
|
||||
}
|
||||
if (typeof obj.imagePath === "string" && obj.imagePath.trim()) {
|
||||
paths.add(obj.imagePath.trim());
|
||||
}
|
||||
const download = obj.download;
|
||||
if (download && typeof download === "object") {
|
||||
const dlPath = (download as Record<string, unknown>).path;
|
||||
if (typeof dlPath === "string" && dlPath.trim()) paths.add(dlPath.trim());
|
||||
if (typeof dlPath === "string" && dlPath.trim()) {
|
||||
paths.add(dlPath.trim());
|
||||
}
|
||||
}
|
||||
return [...paths];
|
||||
}
|
||||
|
||||
async function readBrowserProxyFile(filePath: string): Promise<BrowserProxyFile | null> {
|
||||
const stat = await fsPromises.stat(filePath).catch(() => null);
|
||||
if (!stat || !stat.isFile()) return null;
|
||||
if (!stat || !stat.isFile()) {
|
||||
return null;
|
||||
}
|
||||
if (stat.size > BROWSER_PROXY_MAX_FILE_BYTES) {
|
||||
throw new Error(
|
||||
`browser proxy file exceeds ${Math.round(BROWSER_PROXY_MAX_FILE_BYTES / (1024 * 1024))}MB`,
|
||||
@@ -312,16 +344,22 @@ function formatCommand(argv: string[]): string {
|
||||
return argv
|
||||
.map((arg) => {
|
||||
const trimmed = arg.trim();
|
||||
if (!trimmed) return '""';
|
||||
if (!trimmed) {
|
||||
return '""';
|
||||
}
|
||||
const needsQuotes = /\s|"/.test(trimmed);
|
||||
if (!needsQuotes) return trimmed;
|
||||
if (!needsQuotes) {
|
||||
return trimmed;
|
||||
}
|
||||
return `"${trimmed.replace(/"/g, '\\"')}"`;
|
||||
})
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
function truncateOutput(raw: string, maxChars: number): { text: string; truncated: boolean } {
|
||||
if (raw.length <= maxChars) return { text: raw, truncated: false };
|
||||
if (raw.length <= maxChars) {
|
||||
return { text: raw, truncated: false };
|
||||
}
|
||||
return { text: `... (truncated) ${raw.slice(raw.length - maxChars)}`, truncated: true };
|
||||
}
|
||||
|
||||
@@ -337,7 +375,9 @@ function requireExecApprovalsBaseHash(
|
||||
params: SystemExecApprovalsSetParams,
|
||||
snapshot: ExecApprovalsSnapshot,
|
||||
) {
|
||||
if (!snapshot.exists) return;
|
||||
if (!snapshot.exists) {
|
||||
return;
|
||||
}
|
||||
if (!snapshot.hash) {
|
||||
throw new Error("INVALID_REQUEST: exec approvals base hash unavailable; reload and retry");
|
||||
}
|
||||
@@ -380,9 +420,14 @@ async function runCommand(
|
||||
const slice = chunk.length > remaining ? chunk.subarray(0, remaining) : chunk;
|
||||
const str = slice.toString("utf8");
|
||||
outputLen += slice.length;
|
||||
if (target === "stdout") stdout += str;
|
||||
else stderr += str;
|
||||
if (chunk.length > remaining) truncated = true;
|
||||
if (target === "stdout") {
|
||||
stdout += str;
|
||||
} else {
|
||||
stderr += str;
|
||||
}
|
||||
if (chunk.length > remaining) {
|
||||
truncated = true;
|
||||
}
|
||||
};
|
||||
|
||||
child.stdout?.on("data", (chunk) => onChunk(chunk as Buffer, "stdout"));
|
||||
@@ -401,9 +446,13 @@ async function runCommand(
|
||||
}
|
||||
|
||||
const finalize = (exitCode?: number, error?: string | null) => {
|
||||
if (settled) return;
|
||||
if (settled) {
|
||||
return;
|
||||
}
|
||||
settled = true;
|
||||
if (timer) clearTimeout(timer);
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
resolve({
|
||||
exitCode,
|
||||
timedOut,
|
||||
@@ -437,13 +486,17 @@ function resolveEnvPath(env?: Record<string, string>): string[] {
|
||||
function ensureNodePathEnv(): string {
|
||||
ensureOpenClawCliOnPath({ pathEnv: process.env.PATH ?? "" });
|
||||
const current = process.env.PATH ?? "";
|
||||
if (current.trim()) return current;
|
||||
if (current.trim()) {
|
||||
return current;
|
||||
}
|
||||
process.env.PATH = DEFAULT_NODE_PATH;
|
||||
return DEFAULT_NODE_PATH;
|
||||
}
|
||||
|
||||
function resolveExecutable(bin: string, env?: Record<string, string>) {
|
||||
if (bin.includes("/") || bin.includes("\\")) return null;
|
||||
if (bin.includes("/") || bin.includes("\\")) {
|
||||
return null;
|
||||
}
|
||||
const extensions =
|
||||
process.platform === "win32"
|
||||
? (process.env.PATHEXT ?? process.env.PathExt ?? ".EXE;.CMD;.BAT;.COM")
|
||||
@@ -453,7 +506,9 @@ function resolveExecutable(bin: string, env?: Record<string, string>) {
|
||||
for (const dir of resolveEnvPath(env)) {
|
||||
for (const ext of extensions) {
|
||||
const candidate = path.join(dir, bin + ext);
|
||||
if (fs.existsSync(candidate)) return candidate;
|
||||
if (fs.existsSync(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -464,15 +519,21 @@ async function handleSystemWhich(params: SystemWhichParams, env?: Record<string,
|
||||
const found: Record<string, string> = {};
|
||||
for (const bin of bins) {
|
||||
const path = resolveExecutable(bin, env);
|
||||
if (path) found[bin] = path;
|
||||
if (path) {
|
||||
found[bin] = path;
|
||||
}
|
||||
}
|
||||
return { bins: found };
|
||||
}
|
||||
|
||||
function buildExecEventPayload(payload: ExecEventPayload): ExecEventPayload {
|
||||
if (!payload.output) return payload;
|
||||
if (!payload.output) {
|
||||
return payload;
|
||||
}
|
||||
const trimmed = payload.output.trim();
|
||||
if (!trimmed) return payload;
|
||||
if (!trimmed) {
|
||||
return payload;
|
||||
}
|
||||
const { text } = truncateOutput(trimmed, OUTPUT_EVENT_TAIL);
|
||||
return { ...payload, output: text };
|
||||
}
|
||||
@@ -552,9 +613,13 @@ export async function runNodeHost(opts: NodeHostRunOptions): Promise<void> {
|
||||
deviceIdentity: loadOrCreateDeviceIdentity(),
|
||||
tlsFingerprint: gateway.tlsFingerprint,
|
||||
onEvent: (evt) => {
|
||||
if (evt.event !== "node.invoke.request") return;
|
||||
if (evt.event !== "node.invoke.request") {
|
||||
return;
|
||||
}
|
||||
const payload = coerceNodeInvokePayload(evt.payload);
|
||||
if (!payload) return;
|
||||
if (!payload) {
|
||||
return;
|
||||
}
|
||||
void handleInvoke(payload, client, skillBins);
|
||||
},
|
||||
onConnectError: (err) => {
|
||||
@@ -711,7 +776,9 @@ async function handleInvoke(
|
||||
}
|
||||
const rawQuery = params.query ?? {};
|
||||
for (const [key, value] of Object.entries(rawQuery)) {
|
||||
if (value === undefined || value === null) continue;
|
||||
if (value === undefined || value === null) {
|
||||
continue;
|
||||
}
|
||||
query[key] = typeof value === "string" ? value : String(value);
|
||||
}
|
||||
const dispatcher = createBrowserRouteDispatcher(createBrowserControlContext());
|
||||
@@ -738,7 +805,9 @@ async function handleInvoke(
|
||||
typeof result === "object" && result !== null ? (result as Record<string, unknown>) : {};
|
||||
const profiles = Array.isArray(obj.profiles) ? obj.profiles : [];
|
||||
obj.profiles = profiles.filter((entry) => {
|
||||
if (!entry || typeof entry !== "object") return false;
|
||||
if (!entry || typeof entry !== "object") {
|
||||
return false;
|
||||
}
|
||||
const name = (entry as Record<string, unknown>).name;
|
||||
return typeof name === "string" && allowedProfiles.includes(name);
|
||||
});
|
||||
@@ -761,7 +830,9 @@ async function handleInvoke(
|
||||
}
|
||||
}),
|
||||
);
|
||||
if (loaded.length > 0) files = loaded;
|
||||
if (loaded.length > 0) {
|
||||
files = loaded;
|
||||
}
|
||||
}
|
||||
const payload: BrowserProxyResult = files ? { result, files } : { result };
|
||||
await sendInvokeResult(client, frame, {
|
||||
@@ -996,7 +1067,9 @@ async function handleInvoke(
|
||||
if (analysisOk) {
|
||||
for (const segment of segments) {
|
||||
const pattern = segment.resolution?.resolvedPath ?? "";
|
||||
if (pattern) addAllowlistEntry(approvals.file, agentId, pattern);
|
||||
if (pattern) {
|
||||
addAllowlistEntry(approvals.file, agentId, pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1023,7 +1096,9 @@ async function handleInvoke(
|
||||
if (allowlistMatches.length > 0) {
|
||||
const seen = new Set<string>();
|
||||
for (const match of allowlistMatches) {
|
||||
if (!match?.pattern || seen.has(match.pattern)) continue;
|
||||
if (!match?.pattern || seen.has(match.pattern)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(match.pattern);
|
||||
recordAllowlistUse(
|
||||
approvals.file,
|
||||
@@ -1105,12 +1180,16 @@ function decodeParams<T>(raw?: string | null): T {
|
||||
}
|
||||
|
||||
function coerceNodeInvokePayload(payload: unknown): NodeInvokeRequestPayload | null {
|
||||
if (!payload || typeof payload !== "object") return null;
|
||||
if (!payload || typeof payload !== "object") {
|
||||
return null;
|
||||
}
|
||||
const obj = payload as Record<string, unknown>;
|
||||
const id = typeof obj.id === "string" ? obj.id.trim() : "";
|
||||
const nodeId = typeof obj.nodeId === "string" ? obj.nodeId.trim() : "";
|
||||
const command = typeof obj.command === "string" ? obj.command.trim() : "";
|
||||
if (!id || !nodeId || !command) return null;
|
||||
if (!id || !nodeId || !command) {
|
||||
return null;
|
||||
}
|
||||
const paramsJSON =
|
||||
typeof obj.paramsJSON === "string"
|
||||
? obj.paramsJSON
|
||||
|
||||
Reference in New Issue
Block a user