fix(commands): split chat command listing surface

This commit is contained in:
Vincent Koc
2026-04-11 16:57:50 +01:00
parent da127a3a29
commit 1f1b504980
3 changed files with 75 additions and 63 deletions

View File

@@ -3,12 +3,9 @@ import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalLowercaseString,
} from "../shared/string-coerce.js";
import {
type CommandNormalizeOptions,
listChatCommands,
listChatCommandsForConfig,
normalizeCommandBody,
} from "./commands-registry.js";
import { listChatCommands, listChatCommandsForConfig } from "./commands-registry-list.js";
import { normalizeCommandBody } from "./commands-registry-normalize.js";
import type { CommandNormalizeOptions } from "./commands-registry.types.js";
import { isAbortTrigger } from "./reply/abort-primitives.js";
import { stripInboundMetadata } from "./reply/strip-inbound-meta.js";

View File

@@ -0,0 +1,61 @@
import type { SkillCommandSpec } from "../agents/skills.js";
import { isCommandFlagEnabled } from "../config/commands.js";
import type { OpenClawConfig } from "../config/types.js";
import { getChatCommands } from "./commands-registry.data.js";
import type { ChatCommandDefinition } from "./commands-registry.types.js";
function buildSkillCommandDefinitions(skillCommands?: SkillCommandSpec[]): ChatCommandDefinition[] {
if (!skillCommands || skillCommands.length === 0) {
return [];
}
return skillCommands.map((spec) => ({
key: `skill:${spec.skillName}`,
nativeName: spec.name,
description: spec.description,
textAliases: [`/${spec.name}`],
acceptsArgs: true,
argsParsing: "none",
scope: "both",
category: "tools",
}));
}
export function listChatCommands(params?: {
skillCommands?: SkillCommandSpec[];
}): ChatCommandDefinition[] {
const commands = getChatCommands();
if (!params?.skillCommands?.length) {
return [...commands];
}
return [...commands, ...buildSkillCommandDefinitions(params.skillCommands)];
}
export function isCommandEnabled(cfg: OpenClawConfig, commandKey: string): boolean {
if (commandKey === "config") {
return isCommandFlagEnabled(cfg, "config");
}
if (commandKey === "mcp") {
return isCommandFlagEnabled(cfg, "mcp");
}
if (commandKey === "plugins") {
return isCommandFlagEnabled(cfg, "plugins");
}
if (commandKey === "debug") {
return isCommandFlagEnabled(cfg, "debug");
}
if (commandKey === "bash") {
return isCommandFlagEnabled(cfg, "bash");
}
return true;
}
export function listChatCommandsForConfig(
cfg: OpenClawConfig,
params?: { skillCommands?: SkillCommandSpec[] },
): ChatCommandDefinition[] {
const base = getChatCommands().filter((command) => isCommandEnabled(cfg, command.key));
if (!params?.skillCommands?.length) {
return base;
}
return [...base, ...buildSkillCommandDefinitions(params.skillCommands)];
}

View File

@@ -2,12 +2,16 @@ import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../agents/defaults.js";
import { resolveConfiguredModelRef } from "../agents/model-selection.js";
import type { SkillCommandSpec } from "../agents/skills.js";
import { getChannelPlugin } from "../channels/plugins/index.js";
import { isCommandFlagEnabled } from "../config/commands.js";
import type { OpenClawConfig } from "../config/types.js";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalLowercaseString,
} from "../shared/string-coerce.js";
import {
isCommandEnabled,
listChatCommands,
listChatCommandsForConfig,
} from "./commands-registry-list.js";
import { normalizeCommandBody, resolveTextCommand } from "./commands-registry-normalize.js";
import { getChatCommands, getNativeCommandSurfaces } from "./commands-registry.data.js";
import type {
@@ -23,6 +27,12 @@ import type {
ShouldHandleTextCommandsParams,
} from "./commands-registry.types.js";
export {
isCommandEnabled,
listChatCommands,
listChatCommandsForConfig,
} from "./commands-registry-list.js";
export {
getCommandDetection,
maybeResolveTextAlias,
@@ -44,62 +54,6 @@ export type {
ShouldHandleTextCommandsParams,
} from "./commands-registry.types.js";
function buildSkillCommandDefinitions(skillCommands?: SkillCommandSpec[]): ChatCommandDefinition[] {
if (!skillCommands || skillCommands.length === 0) {
return [];
}
return skillCommands.map((spec) => ({
key: `skill:${spec.skillName}`,
nativeName: spec.name,
description: spec.description,
textAliases: [`/${spec.name}`],
acceptsArgs: true,
argsParsing: "none",
scope: "both",
category: "tools",
}));
}
export function listChatCommands(params?: {
skillCommands?: SkillCommandSpec[];
}): ChatCommandDefinition[] {
const commands = getChatCommands();
if (!params?.skillCommands?.length) {
return [...commands];
}
return [...commands, ...buildSkillCommandDefinitions(params.skillCommands)];
}
export function isCommandEnabled(cfg: OpenClawConfig, commandKey: string): boolean {
if (commandKey === "config") {
return isCommandFlagEnabled(cfg, "config");
}
if (commandKey === "mcp") {
return isCommandFlagEnabled(cfg, "mcp");
}
if (commandKey === "plugins") {
return isCommandFlagEnabled(cfg, "plugins");
}
if (commandKey === "debug") {
return isCommandFlagEnabled(cfg, "debug");
}
if (commandKey === "bash") {
return isCommandFlagEnabled(cfg, "bash");
}
return true;
}
export function listChatCommandsForConfig(
cfg: OpenClawConfig,
params?: { skillCommands?: SkillCommandSpec[] },
): ChatCommandDefinition[] {
const base = getChatCommands().filter((command) => isCommandEnabled(cfg, command.key));
if (!params?.skillCommands?.length) {
return base;
}
return [...base, ...buildSkillCommandDefinitions(params.skillCommands)];
}
function resolveNativeName(command: ChatCommandDefinition, provider?: string): string | undefined {
if (!command.nativeName) {
return undefined;