mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 09:41:11 +00:00
refactor: dedupe plugin trimmed readers
This commit is contained in:
@@ -43,7 +43,9 @@ function normalizePathList(value: unknown): string[] {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
}
|
||||
return value.map((entry) => (typeof entry === "string" ? entry.trim() : "")).filter(Boolean);
|
||||
return value
|
||||
.map((entry) => normalizeOptionalString(entry))
|
||||
.filter((entry): entry is string => Boolean(entry));
|
||||
}
|
||||
|
||||
export function normalizeBundlePathList(value: unknown): string[] {
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
type ClawHubPackageVersion,
|
||||
} from "../infra/clawhub.js";
|
||||
import { formatErrorMessage } from "../infra/errors.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import { resolveCompatibilityHostVersion } from "../version.js";
|
||||
import type { InstallSafetyOverrides } from "./install-security-scan.js";
|
||||
import { installPluginFromArchive, type InstallPluginResult } from "./install.js";
|
||||
@@ -164,7 +165,7 @@ function resolveRequestedVersion(params: {
|
||||
}
|
||||
|
||||
function readTrimmedString(value: unknown): string | null {
|
||||
return typeof value === "string" ? value.trim() : null;
|
||||
return normalizeOptionalString(value) ?? null;
|
||||
}
|
||||
|
||||
function normalizeClawHubRelativePath(value: unknown): string | null {
|
||||
|
||||
@@ -349,8 +349,7 @@ function loadApprovalsFromDisk(): PluginBindingApprovalsFile {
|
||||
pluginId: typeof entry.pluginId === "string" ? entry.pluginId : "",
|
||||
pluginName: typeof entry.pluginName === "string" ? entry.pluginName : undefined,
|
||||
channel: typeof entry.channel === "string" ? normalizeChannel(entry.channel) : "",
|
||||
accountId:
|
||||
typeof entry.accountId === "string" ? entry.accountId.trim() || "default" : "default",
|
||||
accountId: normalizeOptionalString(entry.accountId) ?? "default",
|
||||
approvedAt:
|
||||
typeof entry.approvedAt === "number" && Number.isFinite(entry.approvedAt)
|
||||
? Math.floor(entry.approvedAt)
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
unscopedPackageName,
|
||||
} from "../infra/install-safe-path.js";
|
||||
import { type NpmIntegrityDrift, type NpmSpecResolution } from "../infra/install-source-utils.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import { CONFIG_DIR, resolveUserPath } from "../utils.js";
|
||||
import type { InstallSecurityScanResult } from "./install-security-scan.js";
|
||||
import type { InstallSafetyOverrides } from "./install-security-scan.js";
|
||||
@@ -624,7 +625,7 @@ async function installPluginFromPackageDir(
|
||||
}
|
||||
const extensions = extensionsResult.entries;
|
||||
|
||||
const pkgName = typeof manifest.name === "string" ? manifest.name.trim() : "";
|
||||
const pkgName = normalizeOptionalString(manifest.name) ?? "";
|
||||
const npmPluginId = pkgName || "plugin";
|
||||
|
||||
// Prefer the canonical `id` from openclaw.plugin.json over the npm package name.
|
||||
|
||||
@@ -9,6 +9,7 @@ import type { PluginInstallRecord } from "../config/types.plugins.js";
|
||||
import type { GatewayRequestHandler } from "../gateway/server-methods/types.js";
|
||||
import { openBoundaryFileSync } from "../infra/boundary-file-read.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { buildPluginApi } from "./api-builder.js";
|
||||
import { inspectBundleMcpRuntimeSupport } from "./bundle-mcp.js";
|
||||
@@ -855,8 +856,8 @@ function buildProvenanceIndex(params: {
|
||||
matcher: createPathMatcher(),
|
||||
};
|
||||
const trackedPaths = [install.installPath, install.sourcePath]
|
||||
.map((entry) => (typeof entry === "string" ? entry.trim() : ""))
|
||||
.filter(Boolean);
|
||||
.map((entry) => normalizeOptionalString(entry))
|
||||
.filter((entry): entry is string => Boolean(entry));
|
||||
if (trackedPaths.length === 0) {
|
||||
rule.trackedWithoutPaths = true;
|
||||
} else {
|
||||
|
||||
@@ -266,12 +266,9 @@ function mergePackageChannelMetaIntoChannelConfigs(params: {
|
||||
}
|
||||
|
||||
const existing = params.channelConfigs[channelId];
|
||||
const label =
|
||||
existing.label ??
|
||||
(typeof params.packageChannel?.label === "string" ? params.packageChannel.label.trim() : "");
|
||||
const label = existing.label ?? normalizeOptionalString(params.packageChannel?.label) ?? "";
|
||||
const description =
|
||||
existing.description ??
|
||||
(typeof params.packageChannel?.blurb === "string" ? params.packageChannel.blurb.trim() : "");
|
||||
existing.description ?? normalizeOptionalString(params.packageChannel?.blurb) ?? "";
|
||||
const preferOver =
|
||||
existing.preferOver ?? normalizePreferredPluginIds(params.packageChannel?.preferOver);
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { resolveEnvApiKey } from "../agents/model-auth-env.js";
|
||||
import type { OpenClawConfig } from "../config/types.js";
|
||||
import type { SecretInput } from "../config/types.secrets.js";
|
||||
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeStringifiedOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import type { WizardPrompter } from "../wizard/prompts.js";
|
||||
import {
|
||||
resolveSecretInputModeForEnvSelection,
|
||||
@@ -29,7 +32,7 @@ export {
|
||||
const DEFAULT_KEY_PREVIEW = { head: 4, tail: 4 };
|
||||
|
||||
export function normalizeApiKeyInput(raw: string): string {
|
||||
const trimmed = String(raw ?? "").trim();
|
||||
const trimmed = normalizeStringifiedOptionalString(raw) ?? "";
|
||||
if (!trimmed) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@ import {
|
||||
isValidFileSecretRefId,
|
||||
resolveDefaultSecretProviderAlias,
|
||||
} from "../secrets/ref-contract.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeOptionalString,
|
||||
normalizeStringifiedOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import type { WizardPrompter } from "../wizard/prompts.js";
|
||||
|
||||
let secretResolvePromise: Promise<typeof import("../secrets/resolve.js")> | undefined;
|
||||
@@ -109,7 +112,7 @@ async function promptEnvSecretRefForSetup(params: {
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
const envCandidate = String(envVarRaw ?? "").trim();
|
||||
const envCandidate = normalizeStringifiedOptionalString(envVarRaw) ?? "";
|
||||
const envVar =
|
||||
envCandidate && isValidEnvSecretRefId(envCandidate) ? envCandidate : params.defaultEnvVar;
|
||||
if (!envVar) {
|
||||
@@ -218,7 +221,7 @@ async function promptProviderSecretRefForSetup(params: {
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
const id = String(idRaw ?? "").trim() || idDefault;
|
||||
const id = normalizeStringifiedOptionalString(idRaw) || idDefault;
|
||||
const ref: SecretRef = {
|
||||
source: providerEntry.source,
|
||||
provider: selectedProvider,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { normalizeProviderId } from "../agents/provider-id.js";
|
||||
import type { ModelProviderConfig } from "../config/types.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import type { ProviderCatalogContext, ProviderCatalogResult } from "./types.js";
|
||||
|
||||
export function findCatalogTemplate(params: {
|
||||
@@ -37,8 +40,7 @@ export async function buildSingleProviderApiKeyCatalog(params: {
|
||||
([configuredProviderId]) => normalizeProviderId(configuredProviderId) === providerId,
|
||||
)?.[1]
|
||||
: undefined;
|
||||
const explicitBaseUrl =
|
||||
typeof explicitProvider?.baseUrl === "string" ? explicitProvider.baseUrl.trim() : "";
|
||||
const explicitBaseUrl = normalizeOptionalString(explicitProvider?.baseUrl) ?? "";
|
||||
|
||||
return {
|
||||
provider: {
|
||||
|
||||
@@ -8,6 +8,10 @@ import {
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { ModelDefinitionConfig } from "../config/types.models.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import {
|
||||
normalizeOptionalString,
|
||||
normalizeStringifiedOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import { normalizeOptionalSecretInput } from "../utils/normalize-secret-input.js";
|
||||
import type { WizardPrompter } from "../wizard/prompts.js";
|
||||
import { applyAuthProfileConfig } from "./provider-auth-helpers.js";
|
||||
@@ -53,7 +57,7 @@ export async function discoverOpenAICompatibleLocalModels(params: {
|
||||
const url = `${trimmedBaseUrl}/models`;
|
||||
|
||||
try {
|
||||
const trimmedApiKey = params.apiKey?.trim();
|
||||
const trimmedApiKey = normalizeOptionalString(params.apiKey);
|
||||
const response = await fetch(url, {
|
||||
headers: trimmedApiKey ? { Authorization: `Bearer ${trimmedApiKey}` } : undefined,
|
||||
signal: AbortSignal.timeout(5000),
|
||||
@@ -70,7 +74,7 @@ export async function discoverOpenAICompatibleLocalModels(params: {
|
||||
}
|
||||
|
||||
return models
|
||||
.map((model) => ({ id: typeof model.id === "string" ? model.id.trim() : "" }))
|
||||
.map((model) => ({ id: normalizeOptionalString(model.id) ?? "" }))
|
||||
.filter((model) => Boolean(model.id))
|
||||
.map((model) => {
|
||||
const modelId = model.id;
|
||||
@@ -218,8 +222,8 @@ export async function promptAndConfigureOpenAICompatibleSelfHostedProvider(
|
||||
const baseUrl = String(baseUrlRaw ?? "")
|
||||
.trim()
|
||||
.replace(/\/+$/, "");
|
||||
const apiKey = String(apiKeyRaw ?? "").trim();
|
||||
const modelId = String(modelIdRaw ?? "").trim();
|
||||
const apiKey = normalizeStringifiedOptionalString(apiKeyRaw) ?? "";
|
||||
const modelId = normalizeStringifiedOptionalString(modelIdRaw) ?? "";
|
||||
const credential: AuthProfileCredential = {
|
||||
type: "api_key",
|
||||
provider: params.providerId,
|
||||
|
||||
@@ -15,7 +15,10 @@ import {
|
||||
NODE_SYSTEM_RUN_COMMANDS,
|
||||
} from "../infra/node-commands.js";
|
||||
import { normalizePluginGatewayMethodScope } from "../shared/gateway-method-policy.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeOptionalString,
|
||||
normalizeStringifiedOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { buildPluginApi } from "./api-builder.js";
|
||||
import { registerPluginCommand, validatePluginCommandDefinition } from "./command-registration.js";
|
||||
@@ -611,7 +614,8 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
? (registration as OpenClawPluginChannelRegistration)
|
||||
: { plugin: registration as ChannelPlugin };
|
||||
const plugin = normalized.plugin;
|
||||
const id = typeof plugin?.id === "string" ? plugin.id.trim() : String(plugin?.id ?? "").trim();
|
||||
const id =
|
||||
normalizeOptionalString(plugin?.id) ?? normalizeStringifiedOptionalString(plugin?.id) ?? "";
|
||||
if (!id) {
|
||||
pushDiagnostic({
|
||||
level: "error",
|
||||
|
||||
Reference in New Issue
Block a user