mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 09:41:11 +00:00
refactor: dedupe gateway helper readers
This commit is contained in:
@@ -17,7 +17,11 @@ import {
|
||||
ssrfPolicyFromDangerouslyAllowPrivateNetwork,
|
||||
type SsrFPolicy,
|
||||
} from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
import { isRecord, resolveUserPath } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
isRecord,
|
||||
normalizeOptionalString,
|
||||
resolveUserPath,
|
||||
} from "openclaw/plugin-sdk/text-runtime";
|
||||
|
||||
const DEFAULT_COMFY_LOCAL_BASE_URL = "http://127.0.0.1:8188";
|
||||
const DEFAULT_COMFY_CLOUD_BASE_URL = "https://cloud.comfy.org";
|
||||
@@ -87,15 +91,6 @@ export function _setComfyFetchGuardForTesting(impl: typeof fetchWithSsrFGuard |
|
||||
comfyFetchGuard = impl ?? fetchWithSsrFGuard;
|
||||
}
|
||||
|
||||
function readConfigString(config: ComfyProviderConfig, key: string): string | undefined {
|
||||
const value = config[key];
|
||||
if (typeof value !== "string") {
|
||||
return undefined;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed ? trimmed : undefined;
|
||||
}
|
||||
|
||||
function readConfigBoolean(config: ComfyProviderConfig, key: string): boolean | undefined {
|
||||
const value = config[key];
|
||||
return typeof value === "boolean" ? value : undefined;
|
||||
@@ -161,11 +156,11 @@ export function getComfyCapabilityConfig(
|
||||
}
|
||||
|
||||
export function resolveComfyMode(config: ComfyProviderConfig): ComfyMode {
|
||||
return readConfigString(config, "mode") === "cloud" ? "cloud" : "local";
|
||||
return normalizeOptionalString(config.mode) === "cloud" ? "cloud" : "local";
|
||||
}
|
||||
|
||||
function getRequiredConfigString(config: ComfyProviderConfig, key: string): string {
|
||||
const value = readConfigString(config, key);
|
||||
const value = normalizeOptionalString(config[key]);
|
||||
if (!value) {
|
||||
throw new Error(`models.providers.comfy.${key} is required`);
|
||||
}
|
||||
@@ -180,7 +175,7 @@ function resolveComfyWorkflowSource(config: ComfyProviderConfig): {
|
||||
if (isRecord(workflow)) {
|
||||
return { workflow: structuredClone(workflow) };
|
||||
}
|
||||
const workflowPath = readConfigString(config, "workflowPath");
|
||||
const workflowPath = normalizeOptionalString(config.workflowPath);
|
||||
return { workflowPath };
|
||||
}
|
||||
|
||||
@@ -230,7 +225,7 @@ function resolveComfyNetworkPolicy(params: {
|
||||
return {};
|
||||
}
|
||||
|
||||
const hostname = parsed.hostname.trim().toLowerCase();
|
||||
const hostname = normalizeOptionalString(parsed.hostname)?.toLowerCase() ?? "";
|
||||
if (!hostname || !params.allowPrivateNetwork || !isPrivateOrLoopbackHost(hostname)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -17,10 +17,6 @@ type GatewayConnectionDetailResolvers = {
|
||||
resolveGatewayPort?: (cfg?: OpenClawConfig, env?: NodeJS.ProcessEnv) => number;
|
||||
};
|
||||
|
||||
function trimToUndefined(value: string | undefined): string | undefined {
|
||||
return normalizeOptionalString(value);
|
||||
}
|
||||
|
||||
export function buildGatewayConnectionDetailsWithResolvers(
|
||||
options: {
|
||||
config?: OpenClawConfig;
|
||||
@@ -46,7 +42,7 @@ export function buildGatewayConnectionDetailsWithResolvers(
|
||||
const cliUrlOverride = normalizeOptionalString(options.url);
|
||||
const envUrlOverride = cliUrlOverride
|
||||
? undefined
|
||||
: trimToUndefined(process.env.OPENCLAW_GATEWAY_URL);
|
||||
: normalizeOptionalString(process.env.OPENCLAW_GATEWAY_URL);
|
||||
const urlOverride = cliUrlOverride ?? envUrlOverride;
|
||||
const remoteUrl = normalizeOptionalString(remote?.url);
|
||||
const remoteMisconfigured = isRemoteMode && !urlOverride && !remoteUrl;
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
type ApnsRelayConfig,
|
||||
} from "../infra/push-apns.js";
|
||||
import { roleScopesAllow } from "../shared/operator-scope-compat.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
|
||||
const APPROVALS_SCOPE = "operator.approvals";
|
||||
const OPERATOR_ROLE = "operator";
|
||||
@@ -47,7 +48,7 @@ type ApprovalDeliveryState = {
|
||||
};
|
||||
|
||||
function isIosPlatform(platform: string | undefined): boolean {
|
||||
const normalized = platform?.trim().toLowerCase() ?? "";
|
||||
const normalized = normalizeOptionalString(platform)?.toLowerCase() ?? "";
|
||||
return normalized.startsWith("ios") || normalized.startsWith("ipados");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { normalizeOptionalString } from "../../shared/string-coerce.js";
|
||||
|
||||
export const GATEWAY_CLIENT_IDS = {
|
||||
WEBCHAT_UI: "webchat-ui",
|
||||
CONTROL_UI: "openclaw-control-ui",
|
||||
@@ -53,7 +55,7 @@ const GATEWAY_CLIENT_ID_SET = new Set<GatewayClientId>(Object.values(GATEWAY_CLI
|
||||
const GATEWAY_CLIENT_MODE_SET = new Set<GatewayClientMode>(Object.values(GATEWAY_CLIENT_MODES));
|
||||
|
||||
export function normalizeGatewayClientId(raw?: string | null): GatewayClientId | undefined {
|
||||
const normalized = raw?.trim().toLowerCase();
|
||||
const normalized = normalizeOptionalString(raw)?.toLowerCase();
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -67,7 +69,7 @@ export function normalizeGatewayClientName(raw?: string | null): GatewayClientNa
|
||||
}
|
||||
|
||||
export function normalizeGatewayClientMode(raw?: string | null): GatewayClientMode | undefined {
|
||||
const normalized = raw?.trim().toLowerCase();
|
||||
const normalized = normalizeOptionalString(raw)?.toLowerCase();
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { OpenClawConfig } from "../config/types.js";
|
||||
import { resolveSecretInputRef } from "../config/types.secrets.js";
|
||||
import { secretRefKey } from "../secrets/ref-contract.js";
|
||||
import { resolveSecretRefValues } from "../secrets/resolve.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
|
||||
export type SecretInputUnresolvedReasonStyle = "generic" | "detailed"; // pragma: allowlist secret
|
||||
export type ConfiguredSecretInputSource =
|
||||
@@ -9,14 +10,6 @@ export type ConfiguredSecretInputSource =
|
||||
| "secretRef" // pragma: allowlist secret
|
||||
| "fallback";
|
||||
|
||||
function trimToUndefined(value: unknown): string | undefined {
|
||||
if (typeof value !== "string") {
|
||||
return undefined;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : undefined;
|
||||
}
|
||||
|
||||
function buildUnresolvedReason(params: {
|
||||
path: string;
|
||||
style: SecretInputUnresolvedReasonStyle;
|
||||
@@ -48,7 +41,7 @@ export async function resolveConfiguredSecretInputString(params: {
|
||||
defaults: params.config.secrets?.defaults,
|
||||
});
|
||||
if (!ref) {
|
||||
return { value: trimToUndefined(params.value) };
|
||||
return { value: normalizeOptionalString(params.value) };
|
||||
}
|
||||
|
||||
const refLabel = `${ref.source}:${ref.provider}:${ref.id}`;
|
||||
@@ -68,8 +61,8 @@ export async function resolveConfiguredSecretInputString(params: {
|
||||
}),
|
||||
};
|
||||
}
|
||||
const trimmed = resolvedValue.trim();
|
||||
if (trimmed.length === 0) {
|
||||
const trimmed = normalizeOptionalString(resolvedValue);
|
||||
if (!trimmed) {
|
||||
return {
|
||||
unresolvedRefReason: buildUnresolvedReason({
|
||||
path: params.path,
|
||||
@@ -109,7 +102,7 @@ export async function resolveConfiguredSecretInputWithFallback(params: {
|
||||
value: params.value,
|
||||
defaults: params.config.secrets?.defaults,
|
||||
});
|
||||
const configValue = !ref ? trimToUndefined(params.value) : undefined;
|
||||
const configValue = !ref ? normalizeOptionalString(params.value) : undefined;
|
||||
if (configValue) {
|
||||
return {
|
||||
value: configValue,
|
||||
|
||||
@@ -35,6 +35,7 @@ import { enqueueSystemEvent } from "../infra/system-events.js";
|
||||
import { getChildLogger } from "../logging.js";
|
||||
import { normalizeAgentId, toAgentStoreSessionKey } from "../routing/session-key.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
|
||||
export type GatewayCronState = {
|
||||
cron: CronService;
|
||||
@@ -44,14 +45,6 @@ export type GatewayCronState = {
|
||||
|
||||
const CRON_WEBHOOK_TIMEOUT_MS = 10_000;
|
||||
|
||||
function trimToOptionalString(value: unknown): string | undefined {
|
||||
if (typeof value !== "string") {
|
||||
return undefined;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : undefined;
|
||||
}
|
||||
|
||||
function redactWebhookUrl(url: string): string {
|
||||
try {
|
||||
const parsed = new URL(url);
|
||||
@@ -71,7 +64,7 @@ function resolveCronWebhookTarget(params: {
|
||||
legacyNotify?: boolean;
|
||||
legacyWebhook?: string;
|
||||
}): CronWebhookTarget | null {
|
||||
const mode = params.delivery?.mode?.trim().toLowerCase();
|
||||
const mode = normalizeOptionalString(params.delivery?.mode)?.toLowerCase();
|
||||
if (mode === "webhook") {
|
||||
const url = normalizeHttpWebhookUrl(params.delivery?.to);
|
||||
return url ? { url, source: "delivery" } : null;
|
||||
@@ -314,7 +307,7 @@ export function buildGatewayCronService(params: {
|
||||
},
|
||||
sendCronFailureAlert: async ({ job, text, channel, to, mode, accountId }) => {
|
||||
const { agentId, cfg: runtimeConfig } = resolveCronAgent(job.agentId);
|
||||
const webhookToken = trimToOptionalString(params.cfg.cron?.webhookToken);
|
||||
const webhookToken = normalizeOptionalString(params.cfg.cron?.webhookToken);
|
||||
|
||||
// Webhook mode requires a URL - fail closed if missing
|
||||
if (mode === "webhook" && !to) {
|
||||
@@ -375,8 +368,8 @@ export function buildGatewayCronService(params: {
|
||||
onEvent: (evt) => {
|
||||
params.broadcast("cron", evt, { dropIfSlow: true });
|
||||
if (evt.action === "finished") {
|
||||
const webhookToken = trimToOptionalString(params.cfg.cron?.webhookToken);
|
||||
const legacyWebhook = trimToOptionalString(params.cfg.cron?.webhook);
|
||||
const webhookToken = normalizeOptionalString(params.cfg.cron?.webhookToken);
|
||||
const legacyWebhook = normalizeOptionalString(params.cfg.cron?.webhook);
|
||||
const job = cron.getJob(evt.jobId);
|
||||
const legacyNotify = (job as { notify?: unknown } | undefined)?.notify === true;
|
||||
const webhookTarget = resolveCronWebhookTarget({
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import type { NodeRegistry } from "./node-registry.js";
|
||||
|
||||
const isMobilePlatform = (platform: unknown): boolean => {
|
||||
const p = typeof platform === "string" ? platform.trim().toLowerCase() : "";
|
||||
const p = normalizeOptionalString(platform)?.toLowerCase() ?? "";
|
||||
if (!p) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { IncomingMessage } from "node:http";
|
||||
import { normalizeOptionalString } from "../../../shared/string-coerce.js";
|
||||
import {
|
||||
AUTH_RATE_LIMIT_SCOPE_DEVICE_TOKEN,
|
||||
AUTH_RATE_LIMIT_SCOPE_SHARED_SECRET,
|
||||
@@ -40,19 +41,11 @@ export type ConnectAuthDecision = {
|
||||
authMethod: GatewayAuthResult["method"];
|
||||
};
|
||||
|
||||
function trimToUndefined(value: string | undefined): string | undefined {
|
||||
if (!value) {
|
||||
return undefined;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : undefined;
|
||||
}
|
||||
|
||||
function resolveSharedConnectAuth(
|
||||
connectAuth: HandshakeConnectAuth | null | undefined,
|
||||
): { token?: string; password?: string } | undefined {
|
||||
const token = trimToUndefined(connectAuth?.token);
|
||||
const password = trimToUndefined(connectAuth?.password);
|
||||
const token = normalizeOptionalString(connectAuth?.token);
|
||||
const password = normalizeOptionalString(connectAuth?.password);
|
||||
if (!token && !password) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -63,11 +56,11 @@ function resolveDeviceTokenCandidate(connectAuth: HandshakeConnectAuth | null |
|
||||
token?: string;
|
||||
source?: DeviceTokenCandidateSource;
|
||||
} {
|
||||
const explicitDeviceToken = trimToUndefined(connectAuth?.deviceToken);
|
||||
const explicitDeviceToken = normalizeOptionalString(connectAuth?.deviceToken);
|
||||
if (explicitDeviceToken) {
|
||||
return { token: explicitDeviceToken, source: "explicit-device-token" };
|
||||
}
|
||||
const fallbackToken = trimToUndefined(connectAuth?.token);
|
||||
const fallbackToken = normalizeOptionalString(connectAuth?.token);
|
||||
if (!fallbackToken) {
|
||||
return {};
|
||||
}
|
||||
@@ -77,7 +70,7 @@ function resolveDeviceTokenCandidate(connectAuth: HandshakeConnectAuth | null |
|
||||
function resolveBootstrapTokenCandidate(
|
||||
connectAuth: HandshakeConnectAuth | null | undefined,
|
||||
): string | undefined {
|
||||
return trimToUndefined(connectAuth?.bootstrapToken);
|
||||
return normalizeOptionalString(connectAuth?.bootstrapToken);
|
||||
}
|
||||
|
||||
export async function resolveConnectAuthState(params: {
|
||||
|
||||
Reference in New Issue
Block a user