mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-27 17:11:46 +00:00
refactor: dedupe lowercase helper readers
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import type {
|
||||
MSTeamsConversationStoreEntry,
|
||||
StoredConversationReference,
|
||||
@@ -62,8 +63,8 @@ export function findPreferredDmConversationByUserId(
|
||||
}
|
||||
|
||||
matches.sort((a, b) => {
|
||||
const aType = a.reference.conversation?.conversationType?.toLowerCase() ?? "";
|
||||
const bType = b.reference.conversation?.conversationType?.toLowerCase() ?? "";
|
||||
const aType = normalizeLowercaseStringOrEmpty(a.reference.conversation?.conversationType ?? "");
|
||||
const bType = normalizeLowercaseStringOrEmpty(b.reference.conversation?.conversationType ?? "");
|
||||
const aPersonal = aType === "personal" ? 1 : 0;
|
||||
const bPersonal = bType === "personal" ? 1 : 0;
|
||||
if (aPersonal !== bPersonal) {
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
* @see https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/bots-filesv4
|
||||
*/
|
||||
|
||||
import type { DriveItemProperties } from "./graph-upload.js";
|
||||
|
||||
/**
|
||||
* Build a native Teams file card attachment for Bot Framework.
|
||||
*
|
||||
@@ -19,6 +17,9 @@ import type { DriveItemProperties } from "./graph-upload.js";
|
||||
* @param file - DriveItem properties from getDriveItemProperties()
|
||||
* @returns Attachment object for Bot Framework sendActivity()
|
||||
*/
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import type { DriveItemProperties } from "./graph-upload.js";
|
||||
|
||||
export function buildTeamsFileInfoCard(file: DriveItemProperties): {
|
||||
contentType: string;
|
||||
contentUrl: string;
|
||||
@@ -39,7 +40,8 @@ export function buildTeamsFileInfoCard(file: DriveItemProperties): {
|
||||
|
||||
// Extract file extension from filename
|
||||
const lastDot = file.name.lastIndexOf(".");
|
||||
const fileType = lastDot >= 0 ? file.name.slice(lastDot + 1).toLowerCase() : "";
|
||||
const fileType =
|
||||
lastDot >= 0 ? normalizeLowercaseStringOrEmpty(file.name.slice(lastDot + 1)) : "";
|
||||
|
||||
return {
|
||||
contentType: "application/vnd.microsoft.teams.card.file.info",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
type ChunkMode,
|
||||
isSilentReplyText,
|
||||
@@ -305,7 +306,9 @@ export async function buildActivity(
|
||||
|
||||
// Determine conversation type and file type
|
||||
// Teams only accepts base64 data URLs for images
|
||||
const conversationType = conversationRef.conversation?.conversationType?.toLowerCase();
|
||||
const conversationType = normalizeOptionalLowercaseString(
|
||||
conversationRef.conversation?.conversationType,
|
||||
);
|
||||
const isPersonal = conversationType === "personal";
|
||||
const isImage = media.kind === "image";
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
createChannelPairingController,
|
||||
@@ -24,7 +25,7 @@ export async function resolveMSTeamsSenderAccess(params: {
|
||||
const activity = params.activity;
|
||||
const msteamsCfg = params.cfg.channels?.msteams;
|
||||
const conversationId = normalizeMSTeamsConversationId(activity.conversation?.id ?? "unknown");
|
||||
const convType = activity.conversation?.conversationType?.toLowerCase();
|
||||
const convType = normalizeOptionalLowercaseString(activity.conversation?.conversationType);
|
||||
const isDirectMessage = convType === "personal" || (!convType && !activity.conversation?.isGroup);
|
||||
const senderId = activity.from?.aadObjectId ?? activity.from?.id ?? "unknown";
|
||||
const senderName = activity.from?.name ?? activity.from?.id ?? senderId;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import {
|
||||
resolveChannelMediaMaxBytes,
|
||||
type OpenClawConfig,
|
||||
@@ -139,7 +140,9 @@ export async function resolveMSTeamsSendContext(params: {
|
||||
const tokenProvider: MSTeamsAccessTokenProvider = createMSTeamsTokenProvider(app);
|
||||
|
||||
// Determine conversation type from stored reference
|
||||
const storedConversationType = ref.conversation?.conversationType?.toLowerCase() ?? "";
|
||||
const storedConversationType = normalizeLowercaseStringOrEmpty(
|
||||
ref.conversation?.conversationType ?? "",
|
||||
);
|
||||
let conversationType: MSTeamsConversationType;
|
||||
if (storedConversationType === "personal") {
|
||||
conversationType = "personal";
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
|
||||
export type HttpHeaderMap = Record<string, string | string[] | undefined>;
|
||||
|
||||
export function getHeader(headers: HttpHeaderMap, name: string): string | undefined {
|
||||
const target = name.toLowerCase();
|
||||
const target = normalizeLowercaseStringOrEmpty(name);
|
||||
const direct = headers[target];
|
||||
const value =
|
||||
direct ?? Object.entries(headers).find(([key]) => key.toLowerCase() === target)?.[1];
|
||||
direct ??
|
||||
Object.entries(headers).find(([key]) => normalizeLowercaseStringOrEmpty(key) === target)?.[1];
|
||||
if (Array.isArray(value)) {
|
||||
return value[0];
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* Voice mapping and XML utilities for voice call providers.
|
||||
*/
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
|
||||
/**
|
||||
* Escape XML special characters for TwiML and other XML responses.
|
||||
@@ -49,14 +50,14 @@ export function mapVoiceToPolly(voice: string | undefined): string {
|
||||
}
|
||||
|
||||
// Map OpenAI voices to Polly equivalents
|
||||
return OPENAI_TO_POLLY_MAP[voice.toLowerCase()] || DEFAULT_POLLY_VOICE;
|
||||
return OPENAI_TO_POLLY_MAP[normalizeLowercaseStringOrEmpty(voice)] || DEFAULT_POLLY_VOICE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a voice name is a known OpenAI voice.
|
||||
*/
|
||||
export function isOpenAiVoice(voice: string): boolean {
|
||||
return voice.toLowerCase() in OPENAI_TO_POLLY_MAP;
|
||||
return normalizeLowercaseStringOrEmpty(voice) in OPENAI_TO_POLLY_MAP;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import crypto from "node:crypto";
|
||||
import { safeEqualSecret } from "openclaw/plugin-sdk/browser-security-runtime";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { getHeader } from "./http-headers.js";
|
||||
import type { WebhookContext } from "./types.js";
|
||||
|
||||
@@ -190,7 +191,7 @@ function extractHostname(hostHeader: string): string | null {
|
||||
return null; // Malformed IPv6
|
||||
}
|
||||
hostname = hostHeader.substring(1, endBracket);
|
||||
return hostname.toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(hostname);
|
||||
}
|
||||
|
||||
// Handle IPv4/domain with optional port
|
||||
@@ -206,7 +207,7 @@ function extractHostname(hostHeader: string): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
return hostname.toLowerCase();
|
||||
return normalizeLowercaseStringOrEmpty(hostname);
|
||||
}
|
||||
|
||||
function extractHostnameFromHeader(headerValue: string): string | null {
|
||||
|
||||
@@ -13,6 +13,7 @@ import type {
|
||||
MemoryQmdSearchMode,
|
||||
} from "../../../../src/config/types.memory.js";
|
||||
import { normalizeAgentId } from "../../../../src/routing/session-key.js";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../../../../src/shared/string-coerce.js";
|
||||
import { resolveUserPath } from "../../../../src/utils.js";
|
||||
import { splitShellArgs } from "../../../../src/utils/shell-argv.js";
|
||||
|
||||
@@ -107,7 +108,7 @@ const DEFAULT_QMD_SCOPE: SessionSendPolicyConfig = {
|
||||
};
|
||||
|
||||
function sanitizeName(input: string): string {
|
||||
const lower = input.toLowerCase().replace(/[^a-z0-9-]+/g, "-");
|
||||
const lower = normalizeLowercaseStringOrEmpty(input).replace(/[^a-z0-9-]+/g, "-");
|
||||
const trimmed = lower.replace(/^-+|-+$/g, "");
|
||||
return trimmed || "collection";
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { parseAgentSessionKey } from "../../../../src/sessions/session-key-utils.js";
|
||||
import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
} from "../../../../src/shared/string-coerce.js";
|
||||
import type { ResolvedQmdConfig } from "./backend-config.js";
|
||||
|
||||
type ParsedQmdSessionScope = {
|
||||
@@ -15,7 +19,7 @@ export function isQmdScopeAllowed(scope: ResolvedQmdConfig["scope"], sessionKey?
|
||||
const channel = parsed.channel;
|
||||
const chatType = parsed.chatType;
|
||||
const normalizedKey = parsed.normalizedKey ?? "";
|
||||
const rawKey = sessionKey?.trim().toLowerCase() ?? "";
|
||||
const rawKey = normalizeLowercaseStringOrEmpty(sessionKey ?? "");
|
||||
for (const rule of scope.rules ?? []) {
|
||||
if (!rule) {
|
||||
continue;
|
||||
@@ -27,8 +31,8 @@ export function isQmdScopeAllowed(scope: ResolvedQmdConfig["scope"], sessionKey?
|
||||
if (match.chatType && match.chatType !== chatType) {
|
||||
continue;
|
||||
}
|
||||
const normalizedPrefix = match.keyPrefix?.trim().toLowerCase() || undefined;
|
||||
const rawPrefix = match.rawKeyPrefix?.trim().toLowerCase() || undefined;
|
||||
const normalizedPrefix = normalizeOptionalLowercaseString(match.keyPrefix) || undefined;
|
||||
const rawPrefix = normalizeOptionalLowercaseString(match.rawKeyPrefix) || undefined;
|
||||
|
||||
if (rawPrefix && !rawKey.startsWith(rawPrefix)) {
|
||||
continue;
|
||||
@@ -76,7 +80,7 @@ function parseQmdSessionScope(key?: string): ParsedQmdSessionScope {
|
||||
}
|
||||
return {
|
||||
normalizedKey: normalized,
|
||||
channel: parts[0]?.toLowerCase(),
|
||||
channel: normalizeOptionalLowercaseString(parts[0]),
|
||||
chatType: chatType ?? "direct",
|
||||
};
|
||||
}
|
||||
@@ -98,7 +102,7 @@ function normalizeQmdSessionKey(key?: string): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
const parsed = parseAgentSessionKey(trimmed);
|
||||
const normalized = (parsed?.rest ?? trimmed).toLowerCase();
|
||||
const normalized = normalizeLowercaseStringOrEmpty(parsed?.rest ?? trimmed);
|
||||
if (normalized.startsWith("subagent:")) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user