Skip to content

api-commands — 斜杠指令系统契约

包名: @aalis/api-commands
源码: packages/api-commands/src/index.ts
实现: @aalis/plugin-commands

概述

定义斜杠指令系统:指令定义、子指令递归结构、领域 helper useCommandService(ctx)、CommandService 接口。所有插件注册的指令最终汇聚到 CommandService,由 plugin-commands 解析并派发。

关键类型

ts
interface CommandDefinition {
  name: string;                          // 不含前缀 "/"
  description: string;
  visibility?: CapabilityVisibility;     // 'public' | 'restricted'(默认 public)
  // CapabilityVisibility 从 @aalis/api-authority 导入
  arguments?: CommandArgumentDefinition[];
  options?: CommandOptionDefinition[];
  subcommands?: SubcommandDefinition[];  // 子指令递归
  usage?: string;
  examples?: string[];
  action: (ctx: CommandContext) => Promise<string | undefined>;
}

子指令递归

/clear all          → 命中 subcommand "all"
/clear              → 命中 root action(args=[])
/db migrate up      → 三层匹配,命中最深 action

每一层未命中 → 调用当前层级的 action,若该层无 action 则返回 usage 提示。可见性沿树继承(restricted 父分组 → restricted 子节点,除非子节点重新声明),可在 authority 配置的 authorityOverrides 里按能力键单独改写最低等级(key 形如 command:clear.all,值为整数等级)。

领域 Helper

ts
const commands = useCommandService(ctx);
commands.command(name: string, description?: string, meta?: CommandMeta): CommandBuilder;

helper 内部使用 ctx.getService('commands');服务未 provide 时 command() 调用会被 whenService 自动延迟到服务就绪。

服务接口(节选)

ts
interface CommandService {
  prefix: string;                                           // 通常是 "/"
  command(name: string, description?: string, meta?: CommandMeta): CommandBuilder;   // 插件侧用 useCommandService(ctx).command
  unregister(name: string, contextId?: string): void;
  unregisterByPlugin(contextId: string): void;
  execute(name: string, ctx: ExecutionInput): Promise<string | undefined>;
  parseCommand(input: string): { name: string; args: string[]; raw: string } | null;
  getAll(): Command[];                                       // 供 WebUI / help 枚举
  setExecutionGuard(guard: ExecutionGuard): void;
}

典型用法

ts
const commands = useCommandService(ctx);
commands.command({
  name: 'persona',
  description: '查看/切换人格',
  visibility: 'restricted',
  arguments: [{ name: 'persona', type: 'string', required: false }],
  subcommands: [
    {
      name: 'list',
      description: '列出可选人格',
      action: async () => listPersonas().join('\n'),
    },
  ],
  action: async (ctx) => {
    if (!ctx.args.length) return getCurrentPersona();
    return await setPersona(ctx.args[0]);
  },
});

实现者

相关

  • ExecutionGuardapi-authority
  • ExecutionInput.skipConfirm 用于受信系统源(scheduler 等)跳过受限确认弹窗;authorize 仍生效