mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-21 13:44:03 +00:00
refactor: dedupe plugin lowercase helpers
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import { safeEqualSecret } from "openclaw/plugin-sdk/browser-security-runtime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { z } from "zod";
|
||||
import type { PluginRuntime } from "../api.js";
|
||||
import {
|
||||
@@ -309,7 +310,7 @@ function extractSharedSecret(req: IncomingMessage): string {
|
||||
const authHeader = Array.isArray(req.headers.authorization)
|
||||
? String(req.headers.authorization[0] ?? "")
|
||||
: String(req.headers.authorization ?? "");
|
||||
if (authHeader.toLowerCase().startsWith("bearer ")) {
|
||||
if (normalizeLowercaseStringOrEmpty(authHeader).startsWith("bearer ")) {
|
||||
return authHeader.slice("bearer ".length).trim();
|
||||
}
|
||||
const sharedHeader = req.headers["x-openclaw-webhook-secret"];
|
||||
|
||||
@@ -2,6 +2,7 @@ import fs from "node:fs";
|
||||
import { createRequire } from "node:module";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import { resolveGitHeadPath } from "./git-root.js";
|
||||
import { resolveOpenClawPackageRootSync } from "./openclaw-root.js";
|
||||
|
||||
@@ -17,7 +18,7 @@ const formatCommit = (value?: string | null) => {
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
return match[0].slice(0, 7).toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(match[0].slice(0, 7));
|
||||
};
|
||||
|
||||
const cachedGitCommitBySearchDir = new Map<string, string | null>();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import path from "node:path";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
|
||||
const NOT_FOUND_CODES = new Set(["ENOENT", "ENOTDIR"]);
|
||||
const SYMLINK_OPEN_CODES = new Set(["ELOOP", "EINVAL", "ENOTSUP"]);
|
||||
@@ -11,7 +12,7 @@ export function normalizeWindowsPathForComparison(input: string): string {
|
||||
normalized = `\\\\${normalized.slice(4)}`;
|
||||
}
|
||||
}
|
||||
return normalized.replaceAll("/", "\\").toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(normalized.replaceAll("/", "\\"));
|
||||
}
|
||||
|
||||
export function isNodeError(value: unknown): value is NodeJS.ErrnoException {
|
||||
|
||||
@@ -2,7 +2,10 @@ import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import JSON5 from "json5";
|
||||
import { matchBoundaryFileOpenFailure, openBoundaryFileSync } from "../infra/boundary-file-read.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import { isRecord } from "../utils.js";
|
||||
import { DEFAULT_PLUGIN_ENTRY_CANDIDATES, PLUGIN_MANIFEST_FILENAME } from "./manifest.js";
|
||||
import type { PluginBundleFormat } from "./types.js";
|
||||
@@ -77,7 +80,7 @@ function hasInlineCapabilityValue(value: unknown): boolean {
|
||||
|
||||
function slugifyPluginId(raw: string | undefined, rootDir: string): string {
|
||||
const fallback = path.basename(rootDir);
|
||||
const source = (raw?.trim() || fallback).toLowerCase();
|
||||
const source = normalizeLowercaseStringOrEmpty(raw) || normalizeLowercaseStringOrEmpty(fallback);
|
||||
const slug = source
|
||||
.replace(/[^a-z0-9]+/g, "-")
|
||||
.replace(/-+/g, "-")
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { logVerbose } from "../globals.js";
|
||||
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import {
|
||||
clearPluginCommands,
|
||||
clearPluginCommandsForPlugin,
|
||||
@@ -166,7 +169,7 @@ export function registerPluginCommand(
|
||||
description,
|
||||
};
|
||||
const invocationKeys = listPluginInvocationKeys(normalizedCommand);
|
||||
const key = `/${name.toLowerCase()}`;
|
||||
const key = `/${normalizeLowercaseStringOrEmpty(name)}`;
|
||||
|
||||
// Check for duplicate registration
|
||||
for (const invocationKey of invocationKeys) {
|
||||
|
||||
@@ -303,7 +303,7 @@ function isExtensionFile(filePath: string): boolean {
|
||||
if (filePath.endsWith(".d.ts")) {
|
||||
return false;
|
||||
}
|
||||
const baseName = path.basename(filePath).toLowerCase();
|
||||
const baseName = normalizeLowercaseStringOrEmpty(path.basename(filePath));
|
||||
return (
|
||||
!baseName.includes(".test.") &&
|
||||
!baseName.includes(".live.test.") &&
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
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 type { WizardPrompter } from "../wizard/prompts.js";
|
||||
import {
|
||||
resolveSecretInputModeForEnvSelection,
|
||||
@@ -76,18 +77,13 @@ export function formatApiKeyPreview(
|
||||
export function normalizeTokenProviderInput(
|
||||
tokenProvider: string | null | undefined,
|
||||
): string | undefined {
|
||||
const normalized = String(tokenProvider ?? "")
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
return normalized || undefined;
|
||||
return normalizeOptionalLowercaseString(tokenProvider);
|
||||
}
|
||||
|
||||
export function normalizeSecretInputModeInput(
|
||||
secretInputMode: string | null | undefined,
|
||||
): SecretInputMode | undefined {
|
||||
const normalized = String(secretInputMode ?? "")
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
const normalized = normalizeOptionalLowercaseString(secretInputMode);
|
||||
if (normalized === "plaintext" || normalized === "ref") {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { normalizeProviderId } from "../agents/provider-id.js";
|
||||
import type { ModelProviderConfig } from "../config/types.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import type { ProviderCatalogContext, ProviderCatalogResult } from "./types.js";
|
||||
|
||||
export function findCatalogTemplate(params: {
|
||||
@@ -12,7 +13,7 @@ export function findCatalogTemplate(params: {
|
||||
params.entries.find(
|
||||
(entry) =>
|
||||
normalizeProviderId(entry.provider) === normalizeProviderId(params.providerId) &&
|
||||
entry.id.toLowerCase() === templateId.toLowerCase(),
|
||||
normalizeLowercaseStringOrEmpty(entry.id) === normalizeLowercaseStringOrEmpty(templateId),
|
||||
),
|
||||
)
|
||||
.find((entry) => entry !== undefined);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
import type {
|
||||
ProviderReasoningOutputMode,
|
||||
ProviderReplayPolicy,
|
||||
@@ -71,7 +72,7 @@ export function buildStrictAnthropicReplayPolicy(
|
||||
* See: https://platform.claude.com/docs/en/build-with-claude/extended-thinking#differences-in-thinking-across-model-versions
|
||||
*/
|
||||
export function shouldPreserveThinkingBlocks(modelId?: string): boolean {
|
||||
const id = (modelId ?? "").toLowerCase();
|
||||
const id = normalizeLowercaseStringOrEmpty(modelId);
|
||||
if (!id.includes("claude")) {
|
||||
return false;
|
||||
}
|
||||
@@ -96,14 +97,14 @@ export function shouldPreserveThinkingBlocks(modelId?: string): boolean {
|
||||
}
|
||||
|
||||
export function buildAnthropicReplayPolicyForModel(modelId?: string): ProviderReplayPolicy {
|
||||
const isClaude = (modelId?.toLowerCase() ?? "").includes("claude");
|
||||
const isClaude = normalizeLowercaseStringOrEmpty(modelId).includes("claude");
|
||||
return buildStrictAnthropicReplayPolicy({
|
||||
dropThinkingBlocks: isClaude && !shouldPreserveThinkingBlocks(modelId),
|
||||
});
|
||||
}
|
||||
|
||||
export function buildNativeAnthropicReplayPolicyForModel(modelId?: string): ProviderReplayPolicy {
|
||||
const isClaude = (modelId?.toLowerCase() ?? "").includes("claude");
|
||||
const isClaude = normalizeLowercaseStringOrEmpty(modelId).includes("claude");
|
||||
return buildStrictAnthropicReplayPolicy({
|
||||
dropThinkingBlocks: isClaude && !shouldPreserveThinkingBlocks(modelId),
|
||||
sanitizeToolCallIds: true,
|
||||
@@ -116,7 +117,7 @@ export function buildHybridAnthropicOrOpenAIReplayPolicy(
|
||||
options: { anthropicModelDropThinkingBlocks?: boolean } = {},
|
||||
): ProviderReplayPolicy | undefined {
|
||||
if (ctx.modelApi === "anthropic-messages" || ctx.modelApi === "bedrock-converse-stream") {
|
||||
const isClaude = (ctx.modelId?.toLowerCase() ?? "").includes("claude");
|
||||
const isClaude = normalizeLowercaseStringOrEmpty(ctx.modelId).includes("claude");
|
||||
return buildStrictAnthropicReplayPolicy({
|
||||
dropThinkingBlocks:
|
||||
options.anthropicModelDropThinkingBlocks &&
|
||||
@@ -187,11 +188,12 @@ export function buildGoogleGeminiReplayPolicy(): ProviderReplayPolicy {
|
||||
export function buildPassthroughGeminiSanitizingReplayPolicy(
|
||||
modelId?: string,
|
||||
): ProviderReplayPolicy {
|
||||
const normalizedModelId = normalizeLowercaseStringOrEmpty(modelId);
|
||||
return {
|
||||
applyAssistantFirstOrderingFix: false,
|
||||
validateGeminiTurns: false,
|
||||
validateAnthropicTurns: false,
|
||||
...((modelId?.toLowerCase() ?? "").includes("gemini")
|
||||
...(normalizedModelId.includes("gemini")
|
||||
? {
|
||||
sanitizeThoughtSignatures: {
|
||||
allowBase64Only: true,
|
||||
|
||||
@@ -6,6 +6,7 @@ import type {
|
||||
} from "@mariozechner/pi-tui";
|
||||
import chalk from "chalk";
|
||||
import { highlight, supportsLanguage } from "cli-highlight";
|
||||
import { normalizeOptionalLowercaseString } from "../../shared/string-coerce.js";
|
||||
import type { SearchableSelectListTheme } from "../components/searchable-select-list.js";
|
||||
import { createSyntaxTheme } from "./syntax-theme.js";
|
||||
|
||||
@@ -46,7 +47,7 @@ function pickHigherContrastText(r: number, g: number, b: number): boolean {
|
||||
}
|
||||
|
||||
function isLightBackground(): boolean {
|
||||
const explicit = process.env.OPENCLAW_THEME?.toLowerCase();
|
||||
const explicit = normalizeOptionalLowercaseString(process.env.OPENCLAW_THEME);
|
||||
if (explicit === "light") {
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user