/** * Command 注册表 * * 管理所有可用的 Commands,支持: * - 注册/注销 Commands * - 按名称查询 * - 搜索 Commands */ import type { Command, CommandSearchResult } from './types.js'; import { commandLoader } from './loader.js'; import { builtinCommands } from './builtin/index.js'; /** * Command 注册表 */ export class CommandRegistry { private commands = new Map(); private initialized = false; /** * 初始化注册表 */ async initialize(workdir: string = process.cwd()): Promise { if (this.initialized) { return; } // 1. 注册内置 Commands for (const command of builtinCommands) { this.register(command); } // 2. 加载用户 Commands const userDir = commandLoader.getUserCommandsDir(); const userCommands = await commandLoader.loadFromDirectory(userDir, 'user'); for (const command of userCommands) { this.register(command); } // 3. 加载项目 Commands const projectDir = commandLoader.getProjectCommandsDir(workdir); const projectCommands = await commandLoader.loadFromDirectory( projectDir, 'project' ); for (const command of projectCommands) { this.register(command); } this.initialized = true; } /** * 注册 Command */ register(command: Command): void { // 项目 Commands 优先级最高,可以覆盖同名的内置/用户 Commands const existing = this.commands.get(command.name); if (existing) { // 优先级: project > user > builtin const priority = { project: 3, user: 2, builtin: 1 }; if (priority[command.source] < priority[existing.source]) { return; // 不覆盖更高优先级的 Command } } this.commands.set(command.name, command); } /** * 注销 Command */ unregister(name: string): boolean { return this.commands.delete(name); } /** * 获取 Command */ get(name: string): Command | undefined { return this.commands.get(name); } /** * 检查 Command 是否存在 */ has(name: string): boolean { return this.commands.has(name); } /** * 获取所有 Commands */ getAll(): Command[] { return Array.from(this.commands.values()); } /** * 搜索 Commands */ search(query: string, limit: number = 10): CommandSearchResult[] { const queryLower = query.toLowerCase(); const results: CommandSearchResult[] = []; for (const command of this.commands.values()) { let score = 0; // 精确名称匹配 if (command.name.toLowerCase() === queryLower) { score = 100; } // 名称前缀匹配 else if (command.name.toLowerCase().startsWith(queryLower)) { score = 80; } // 名称包含匹配 else if (command.name.toLowerCase().includes(queryLower)) { score = 60; } // 描述匹配 else if (command.description?.toLowerCase().includes(queryLower)) { score = 40; } if (score > 0) { results.push({ command, score }); } } // 按分数降序排序 results.sort((a, b) => b.score - a.score); return results.slice(0, limit); } /** * 列出所有 Commands(用于帮助显示) */ list(): Array<{ name: string; description?: string; source: string }> { return this.getAll() .map((cmd) => ({ name: cmd.name, description: cmd.description, source: cmd.source, })) .sort((a, b) => a.name.localeCompare(b.name)); } /** * 重新加载 Commands */ async reload(workdir: string = process.cwd()): Promise { this.commands.clear(); this.initialized = false; await this.initialize(workdir); } /** * 获取统计信息 */ getStats(): { total: number; bySource: Record; } { const commands = this.getAll(); const bySource: Record = {}; for (const command of commands) { bySource[command.source] = (bySource[command.source] || 0) + 1; } return { total: commands.length, bySource, }; } } /** * 全局 Command 注册表实例 */ let commandRegistryInstance: CommandRegistry | null = null; /** * 获取全局 Command 注册表 */ export function getCommandRegistry(): CommandRegistry { if (!commandRegistryInstance) { commandRegistryInstance = new CommandRegistry(); } return commandRegistryInstance; } /** * 重置全局 Command 注册表(用于测试) */ export function resetCommandRegistry(): void { commandRegistryInstance = null; }