mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 16:14:31 +00:00
chore: Enable "curly" rule to avoid single-statement if confusion/errors.
This commit is contained in:
@@ -43,7 +43,9 @@ let cachedDetectionCommands: ChatCommandDefinition[] | null = null;
|
||||
|
||||
function getTextAliasMap(): Map<string, TextAliasSpec> {
|
||||
const commands = getChatCommands();
|
||||
if (cachedTextAliasMap && cachedTextAliasCommands === commands) return cachedTextAliasMap;
|
||||
if (cachedTextAliasMap && cachedTextAliasCommands === commands) {
|
||||
return cachedTextAliasMap;
|
||||
}
|
||||
const map = new Map<string, TextAliasSpec>();
|
||||
for (const command of commands) {
|
||||
// Canonicalize to the *primary* text alias, not `/${key}`. Some command keys are
|
||||
@@ -53,7 +55,9 @@ function getTextAliasMap(): Map<string, TextAliasSpec> {
|
||||
const acceptsArgs = Boolean(command.acceptsArgs);
|
||||
for (const alias of command.textAliases) {
|
||||
const normalized = alias.trim().toLowerCase();
|
||||
if (!normalized) continue;
|
||||
if (!normalized) {
|
||||
continue;
|
||||
}
|
||||
if (!map.has(normalized)) {
|
||||
map.set(normalized, { key: command.key, canonical, acceptsArgs });
|
||||
}
|
||||
@@ -69,7 +73,9 @@ function escapeRegExp(value: string) {
|
||||
}
|
||||
|
||||
function buildSkillCommandDefinitions(skillCommands?: SkillCommandSpec[]): ChatCommandDefinition[] {
|
||||
if (!skillCommands || skillCommands.length === 0) return [];
|
||||
if (!skillCommands || skillCommands.length === 0) {
|
||||
return [];
|
||||
}
|
||||
return skillCommands.map((spec) => ({
|
||||
key: `skill:${spec.skillName}`,
|
||||
nativeName: spec.name,
|
||||
@@ -85,14 +91,22 @@ export function listChatCommands(params?: {
|
||||
skillCommands?: SkillCommandSpec[];
|
||||
}): ChatCommandDefinition[] {
|
||||
const commands = getChatCommands();
|
||||
if (!params?.skillCommands?.length) return [...commands];
|
||||
if (!params?.skillCommands?.length) {
|
||||
return [...commands];
|
||||
}
|
||||
return [...commands, ...buildSkillCommandDefinitions(params.skillCommands)];
|
||||
}
|
||||
|
||||
export function isCommandEnabled(cfg: OpenClawConfig, commandKey: string): boolean {
|
||||
if (commandKey === "config") return cfg.commands?.config === true;
|
||||
if (commandKey === "debug") return cfg.commands?.debug === true;
|
||||
if (commandKey === "bash") return cfg.commands?.bash === true;
|
||||
if (commandKey === "config") {
|
||||
return cfg.commands?.config === true;
|
||||
}
|
||||
if (commandKey === "debug") {
|
||||
return cfg.commands?.debug === true;
|
||||
}
|
||||
if (commandKey === "bash") {
|
||||
return cfg.commands?.bash === true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -101,7 +115,9 @@ export function listChatCommandsForConfig(
|
||||
params?: { skillCommands?: SkillCommandSpec[] },
|
||||
): ChatCommandDefinition[] {
|
||||
const base = getChatCommands().filter((command) => isCommandEnabled(cfg, command.key));
|
||||
if (!params?.skillCommands?.length) return base;
|
||||
if (!params?.skillCommands?.length) {
|
||||
return base;
|
||||
}
|
||||
return [...base, ...buildSkillCommandDefinitions(params.skillCommands)];
|
||||
}
|
||||
|
||||
@@ -112,10 +128,14 @@ const NATIVE_NAME_OVERRIDES: Record<string, Record<string, string>> = {
|
||||
};
|
||||
|
||||
function resolveNativeName(command: ChatCommandDefinition, provider?: string): string | undefined {
|
||||
if (!command.nativeName) return undefined;
|
||||
if (!command.nativeName) {
|
||||
return undefined;
|
||||
}
|
||||
if (provider) {
|
||||
const override = NATIVE_NAME_OVERRIDES[provider]?.[command.key];
|
||||
if (override) return override;
|
||||
if (override) {
|
||||
return override;
|
||||
}
|
||||
}
|
||||
return command.nativeName;
|
||||
}
|
||||
@@ -168,11 +188,15 @@ export function buildCommandText(commandName: string, args?: string): string {
|
||||
function parsePositionalArgs(definitions: CommandArgDefinition[], raw: string): CommandArgValues {
|
||||
const values: CommandArgValues = {};
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return values;
|
||||
if (!trimmed) {
|
||||
return values;
|
||||
}
|
||||
const tokens = trimmed.split(/\s+/).filter(Boolean);
|
||||
let index = 0;
|
||||
for (const definition of definitions) {
|
||||
if (index >= tokens.length) break;
|
||||
if (index >= tokens.length) {
|
||||
break;
|
||||
}
|
||||
if (definition.captureRemaining) {
|
||||
values[definition.name] = tokens.slice(index).join(" ");
|
||||
index = tokens.length;
|
||||
@@ -191,16 +215,22 @@ function formatPositionalArgs(
|
||||
const parts: string[] = [];
|
||||
for (const definition of definitions) {
|
||||
const value = values[definition.name];
|
||||
if (value == null) continue;
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
let rendered: string;
|
||||
if (typeof value === "string") {
|
||||
rendered = value.trim();
|
||||
} else {
|
||||
rendered = String(value);
|
||||
}
|
||||
if (!rendered) continue;
|
||||
if (!rendered) {
|
||||
continue;
|
||||
}
|
||||
parts.push(rendered);
|
||||
if (definition.captureRemaining) break;
|
||||
if (definition.captureRemaining) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return parts.length > 0 ? parts.join(" ") : undefined;
|
||||
}
|
||||
@@ -210,7 +240,9 @@ export function parseCommandArgs(
|
||||
raw?: string,
|
||||
): CommandArgs | undefined {
|
||||
const trimmed = raw?.trim();
|
||||
if (!trimmed) return undefined;
|
||||
if (!trimmed) {
|
||||
return undefined;
|
||||
}
|
||||
if (!command.args || command.argsParsing === "none") {
|
||||
return { raw: trimmed };
|
||||
}
|
||||
@@ -224,11 +256,19 @@ export function serializeCommandArgs(
|
||||
command: ChatCommandDefinition,
|
||||
args?: CommandArgs,
|
||||
): string | undefined {
|
||||
if (!args) return undefined;
|
||||
if (!args) {
|
||||
return undefined;
|
||||
}
|
||||
const raw = args.raw?.trim();
|
||||
if (raw) return raw;
|
||||
if (!args.values || !command.args) return undefined;
|
||||
if (command.formatArgs) return command.formatArgs(args.values);
|
||||
if (raw) {
|
||||
return raw;
|
||||
}
|
||||
if (!args.values || !command.args) {
|
||||
return undefined;
|
||||
}
|
||||
if (command.formatArgs) {
|
||||
return command.formatArgs(args.values);
|
||||
}
|
||||
return formatPositionalArgs(command.args, args.values);
|
||||
}
|
||||
|
||||
@@ -265,7 +305,9 @@ export function resolveCommandArgChoices(params: {
|
||||
model?: string;
|
||||
}): ResolvedCommandArgChoice[] {
|
||||
const { command, arg, cfg } = params;
|
||||
if (!arg.choices) return [];
|
||||
if (!arg.choices) {
|
||||
return [];
|
||||
}
|
||||
const provided = arg.choices;
|
||||
const raw = Array.isArray(provided)
|
||||
? provided
|
||||
@@ -291,27 +333,43 @@ export function resolveCommandArgMenu(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
}): { arg: CommandArgDefinition; choices: ResolvedCommandArgChoice[]; title?: string } | null {
|
||||
const { command, args, cfg } = params;
|
||||
if (!command.args || !command.argsMenu) return null;
|
||||
if (command.argsParsing === "none") return null;
|
||||
if (!command.args || !command.argsMenu) {
|
||||
return null;
|
||||
}
|
||||
if (command.argsParsing === "none") {
|
||||
return null;
|
||||
}
|
||||
const argSpec = command.argsMenu;
|
||||
const argName =
|
||||
argSpec === "auto"
|
||||
? command.args.find((arg) => resolveCommandArgChoices({ command, arg, cfg }).length > 0)?.name
|
||||
: argSpec.arg;
|
||||
if (!argName) return null;
|
||||
if (args?.values && args.values[argName] != null) return null;
|
||||
if (args?.raw && !args.values) return null;
|
||||
if (!argName) {
|
||||
return null;
|
||||
}
|
||||
if (args?.values && args.values[argName] != null) {
|
||||
return null;
|
||||
}
|
||||
if (args?.raw && !args.values) {
|
||||
return null;
|
||||
}
|
||||
const arg = command.args.find((entry) => entry.name === argName);
|
||||
if (!arg) return null;
|
||||
if (!arg) {
|
||||
return null;
|
||||
}
|
||||
const choices = resolveCommandArgChoices({ command, arg, cfg });
|
||||
if (choices.length === 0) return null;
|
||||
if (choices.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const title = argSpec !== "auto" ? argSpec.title : undefined;
|
||||
return { arg, choices, title };
|
||||
}
|
||||
|
||||
export function normalizeCommandBody(raw: string, options?: CommandNormalizeOptions): string {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed.startsWith("/")) return trimmed;
|
||||
if (!trimmed.startsWith("/")) {
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
const newline = trimmed.indexOf("\n");
|
||||
const singleLine = newline === -1 ? trimmed : trimmed.slice(0, newline).trim();
|
||||
@@ -337,15 +395,23 @@ export function normalizeCommandBody(raw: string, options?: CommandNormalizeOpti
|
||||
const lowered = commandBody.toLowerCase();
|
||||
const textAliasMap = getTextAliasMap();
|
||||
const exact = textAliasMap.get(lowered);
|
||||
if (exact) return exact.canonical;
|
||||
if (exact) {
|
||||
return exact.canonical;
|
||||
}
|
||||
|
||||
const tokenMatch = commandBody.match(/^\/([^\s]+)(?:\s+([\s\S]+))?$/);
|
||||
if (!tokenMatch) return commandBody;
|
||||
if (!tokenMatch) {
|
||||
return commandBody;
|
||||
}
|
||||
const [, token, rest] = tokenMatch;
|
||||
const tokenKey = `/${token.toLowerCase()}`;
|
||||
const tokenSpec = textAliasMap.get(tokenKey);
|
||||
if (!tokenSpec) return commandBody;
|
||||
if (rest && !tokenSpec.acceptsArgs) return commandBody;
|
||||
if (!tokenSpec) {
|
||||
return commandBody;
|
||||
}
|
||||
if (rest && !tokenSpec.acceptsArgs) {
|
||||
return commandBody;
|
||||
}
|
||||
const normalizedRest = rest?.trimStart();
|
||||
return normalizedRest ? `${tokenSpec.canonical} ${normalizedRest}` : tokenSpec.canonical;
|
||||
}
|
||||
@@ -357,16 +423,22 @@ export function isCommandMessage(raw: string): boolean {
|
||||
|
||||
export function getCommandDetection(_cfg?: OpenClawConfig): CommandDetection {
|
||||
const commands = getChatCommands();
|
||||
if (cachedDetection && cachedDetectionCommands === commands) return cachedDetection;
|
||||
if (cachedDetection && cachedDetectionCommands === commands) {
|
||||
return cachedDetection;
|
||||
}
|
||||
const exact = new Set<string>();
|
||||
const patterns: string[] = [];
|
||||
for (const cmd of commands) {
|
||||
for (const alias of cmd.textAliases) {
|
||||
const normalized = alias.trim().toLowerCase();
|
||||
if (!normalized) continue;
|
||||
if (!normalized) {
|
||||
continue;
|
||||
}
|
||||
exact.add(normalized);
|
||||
const escaped = escapeRegExp(normalized);
|
||||
if (!escaped) continue;
|
||||
if (!escaped) {
|
||||
continue;
|
||||
}
|
||||
if (cmd.acceptsArgs) {
|
||||
patterns.push(`${escaped}(?:\\s+.+|\\s*:\\s*.*)?`);
|
||||
} else {
|
||||
@@ -384,13 +456,21 @@ export function getCommandDetection(_cfg?: OpenClawConfig): CommandDetection {
|
||||
|
||||
export function maybeResolveTextAlias(raw: string, cfg?: OpenClawConfig) {
|
||||
const trimmed = normalizeCommandBody(raw).trim();
|
||||
if (!trimmed.startsWith("/")) return null;
|
||||
if (!trimmed.startsWith("/")) {
|
||||
return null;
|
||||
}
|
||||
const detection = getCommandDetection(cfg);
|
||||
const normalized = trimmed.toLowerCase();
|
||||
if (detection.exact.has(normalized)) return normalized;
|
||||
if (!detection.regex.test(normalized)) return null;
|
||||
if (detection.exact.has(normalized)) {
|
||||
return normalized;
|
||||
}
|
||||
if (!detection.regex.test(normalized)) {
|
||||
return null;
|
||||
}
|
||||
const tokenMatch = normalized.match(/^\/([^\s:]+)(?:\s|$)/);
|
||||
if (!tokenMatch) return null;
|
||||
if (!tokenMatch) {
|
||||
return null;
|
||||
}
|
||||
const tokenKey = `/${tokenMatch[1]}`;
|
||||
return getTextAliasMap().has(tokenKey) ? tokenKey : null;
|
||||
}
|
||||
@@ -404,23 +484,37 @@ export function resolveTextCommand(
|
||||
} | null {
|
||||
const trimmed = normalizeCommandBody(raw).trim();
|
||||
const alias = maybeResolveTextAlias(trimmed, cfg);
|
||||
if (!alias) return null;
|
||||
if (!alias) {
|
||||
return null;
|
||||
}
|
||||
const spec = getTextAliasMap().get(alias);
|
||||
if (!spec) return null;
|
||||
if (!spec) {
|
||||
return null;
|
||||
}
|
||||
const command = getChatCommands().find((entry) => entry.key === spec.key);
|
||||
if (!command) return null;
|
||||
if (!spec.acceptsArgs) return { command };
|
||||
if (!command) {
|
||||
return null;
|
||||
}
|
||||
if (!spec.acceptsArgs) {
|
||||
return { command };
|
||||
}
|
||||
const args = trimmed.slice(alias.length).trim();
|
||||
return { command, args: args || undefined };
|
||||
}
|
||||
|
||||
export function isNativeCommandSurface(surface?: string): boolean {
|
||||
if (!surface) return false;
|
||||
if (!surface) {
|
||||
return false;
|
||||
}
|
||||
return getNativeCommandSurfaces().has(surface.toLowerCase());
|
||||
}
|
||||
|
||||
export function shouldHandleTextCommands(params: ShouldHandleTextCommandsParams): boolean {
|
||||
if (params.commandSource === "native") return true;
|
||||
if (params.cfg.commands?.text !== false) return true;
|
||||
if (params.commandSource === "native") {
|
||||
return true;
|
||||
}
|
||||
if (params.cfg.commands?.text !== false) {
|
||||
return true;
|
||||
}
|
||||
return !isNativeCommandSurface(params.surface);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user