From 1868f301ed0b210893d6dee63a24474ebd9d6d37 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 7 Apr 2026 23:04:38 +0100 Subject: [PATCH] refactor: dedupe browser trimmed readers --- .../browser/src/browser/bridge-auth-registry.ts | 6 ++++-- extensions/browser/src/browser/client-fetch.ts | 6 ++++-- extensions/browser/src/browser/control-auth.ts | 9 ++++++--- .../browser/src/browser/routes/agent.shared.ts | 5 +++-- extensions/browser/src/browser/routes/utils.ts | 12 +++++------- extensions/browser/src/gateway/browser-request.ts | 15 +++++++++------ 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/extensions/browser/src/browser/bridge-auth-registry.ts b/extensions/browser/src/browser/bridge-auth-registry.ts index ef9346bf340..b83e5ebc4e6 100644 --- a/extensions/browser/src/browser/bridge-auth-registry.ts +++ b/extensions/browser/src/browser/bridge-auth-registry.ts @@ -1,3 +1,5 @@ +import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime"; + type BridgeAuth = { token?: string; password?: string; @@ -11,8 +13,8 @@ export function setBridgeAuthForPort(port: number, auth: BridgeAuth): void { if (!Number.isFinite(port) || port <= 0) { return; } - const token = typeof auth.token === "string" ? auth.token.trim() : ""; - const password = typeof auth.password === "string" ? auth.password.trim() : ""; + const token = normalizeOptionalString(auth.token) ?? ""; + const password = normalizeOptionalString(auth.password) ?? ""; authByPort.set(port, { token: token || undefined, password: password || undefined, diff --git a/extensions/browser/src/browser/client-fetch.ts b/extensions/browser/src/browser/client-fetch.ts index 1a74c0ffa43..ee90a053dde 100644 --- a/extensions/browser/src/browser/client-fetch.ts +++ b/extensions/browser/src/browser/client-fetch.ts @@ -1,3 +1,4 @@ +import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime"; import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime"; import { formatCliCommand } from "../cli/command-format.js"; import { loadConfig } from "../config/config.js"; @@ -141,8 +142,9 @@ function resolveBrowserFetchOperatorHint(url: string): string { } function normalizeErrorMessage(err: unknown): string { - if (err instanceof Error && err.message.trim().length > 0) { - return err.message.trim(); + const message = err instanceof Error ? normalizeOptionalString(err.message) : undefined; + if (message) { + return message; } return String(err); } diff --git a/extensions/browser/src/browser/control-auth.ts b/extensions/browser/src/browser/control-auth.ts index 2852272581a..64cfa77affc 100644 --- a/extensions/browser/src/browser/control-auth.ts +++ b/extensions/browser/src/browser/control-auth.ts @@ -1,4 +1,7 @@ -import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime"; +import { + normalizeLowercaseStringOrEmpty, + normalizeOptionalString, +} from "openclaw/plugin-sdk/text-runtime"; import type { OpenClawConfig } from "../config/config.js"; import { loadConfig } from "../config/config.js"; import { resolveGatewayAuth } from "../gateway/auth.js"; @@ -18,8 +21,8 @@ export function resolveBrowserControlAuth( env, tailscaleMode: cfg?.gateway?.tailscale?.mode, }); - const token = typeof auth.token === "string" ? auth.token.trim() : ""; - const password = typeof auth.password === "string" ? auth.password.trim() : ""; + const token = normalizeOptionalString(auth.token) ?? ""; + const password = normalizeOptionalString(auth.password) ?? ""; return { token: token || undefined, password: password || undefined, diff --git a/extensions/browser/src/browser/routes/agent.shared.ts b/extensions/browser/src/browser/routes/agent.shared.ts index cc82e00d004..ebcdc20d67c 100644 --- a/extensions/browser/src/browser/routes/agent.shared.ts +++ b/extensions/browser/src/browser/routes/agent.shared.ts @@ -1,3 +1,4 @@ +import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime"; import { toBrowserErrorResponse } from "../errors.js"; import type { PwAiModule } from "../pw-ai-module.js"; import { getPwAiModule as getPwAiModuleBase } from "../pw-ai-module.js"; @@ -24,12 +25,12 @@ export function readBody(req: BrowserRequest): Record { } export function resolveTargetIdFromBody(body: Record): string | undefined { - const targetId = typeof body.targetId === "string" ? body.targetId.trim() : ""; + const targetId = normalizeOptionalString(body.targetId) ?? ""; return targetId || undefined; } export function resolveTargetIdFromQuery(query: Record): string | undefined { - const targetId = typeof query.targetId === "string" ? query.targetId.trim() : ""; + const targetId = normalizeOptionalString(query.targetId) ?? ""; return targetId || undefined; } diff --git a/extensions/browser/src/browser/routes/utils.ts b/extensions/browser/src/browser/routes/utils.ts index 2cb7c6dce53..89e7244a986 100644 --- a/extensions/browser/src/browser/routes/utils.ts +++ b/extensions/browser/src/browser/routes/utils.ts @@ -38,11 +38,8 @@ export function jsonError(res: BrowserResponse, status: number, message: string) } export function toStringOrEmpty(value: unknown) { - if (typeof value === "string") { - return value.trim(); - } - if (typeof value === "number" || typeof value === "boolean") { - return String(value).trim(); + if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") { + return normalizeOptionalString(String(value)) ?? ""; } return ""; } @@ -51,8 +48,9 @@ export function toNumber(value: unknown) { if (typeof value === "number" && Number.isFinite(value)) { return value; } - if (typeof value === "string" && value.trim()) { - const parsed = Number(value); + const normalized = typeof value === "string" ? normalizeOptionalString(value) : undefined; + if (normalized) { + const parsed = Number(normalized); return Number.isFinite(parsed) ? parsed : undefined; } return undefined; diff --git a/extensions/browser/src/gateway/browser-request.ts b/extensions/browser/src/gateway/browser-request.ts index aa7ae51e992..724ced98e73 100644 --- a/extensions/browser/src/gateway/browser-request.ts +++ b/extensions/browser/src/gateway/browser-request.ts @@ -1,5 +1,8 @@ import crypto from "node:crypto"; -import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime"; +import { + normalizeLowercaseStringOrEmpty, + normalizeOptionalString, +} from "openclaw/plugin-sdk/text-runtime"; import { ErrorCodes, applyBrowserProxyPaths, @@ -49,7 +52,7 @@ function normalizeNodeKey(value: string) { } function resolveBrowserNode(nodes: NodeSession[], query: string): NodeSession | null { - const q = query.trim(); + const q = normalizeOptionalString(query) ?? ""; if (!q) { return null; } @@ -94,12 +97,12 @@ function resolveBrowserNodeTarget(params: { } const browserNodes = params.nodes.filter((node) => isBrowserNode(node)); if (browserNodes.length === 0) { - if (policy?.node?.trim()) { + if (normalizeOptionalString(policy?.node)) { throw new Error("No connected browser-capable nodes."); } return null; } - const requested = policy?.node?.trim() || ""; + const requested = normalizeOptionalString(policy?.node) ?? ""; if (requested) { const resolved = resolveBrowserNode(browserNodes, requested); if (!resolved) { @@ -130,8 +133,8 @@ export async function handleBrowserGatewayRequest({ context, }: Parameters[0]) { const typed = params as BrowserRequestParams; - const methodRaw = typeof typed.method === "string" ? typed.method.trim().toUpperCase() : ""; - const path = typeof typed.path === "string" ? typed.path.trim() : ""; + const methodRaw = (normalizeOptionalString(typed.method) ?? "").toUpperCase(); + const path = normalizeOptionalString(typed.path) ?? ""; const query = typed.query && typeof typed.query === "object" ? typed.query : undefined; const body = typed.body; const timeoutMs =