diff --git a/src/cli/index.js b/src/cli/index.js index 5241524..9e76542 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -11,7 +11,7 @@ const { createState } = require('../core/state'); const { buildSystemPrompt } = require('../core/context'); const { streamChat } = require('../model/client'); const { executeTool } = require('../tools/dispatcher'); -const { openCommandMenu } = require('../ui/command_menu'); +const { openCommandMenu, hasCommandMatch } = require('../ui/command_menu'); const { handleCommand } = require('./commands'); const { Spinner, truncateThinking } = require('../ui/spinner'); const { renderBanner } = require('../ui/banner'); @@ -27,6 +27,7 @@ const WORKSPACE_NAME = path.basename(WORKSPACE); const USERNAME = os.userInfo().username || 'user'; const PROMPT = `${USERNAME}@${WORKSPACE_NAME} % `; const MENU_PAGE_SIZE = 6; +const SLASH_COMMANDS = new Set(['/new', '/resume', '/allow', '/model', '/status', '/compact', '/config', '/help', '/exit']); const config = ensureConfig(); const state = createState(config, WORKSPACE); @@ -64,6 +65,22 @@ let menuInjectedCommand = null; let menuAbortController = null; let menuJustClosedInjected = false; +function printNotice(message) { + console.log(''); + console.log(message); + console.log(''); +} + +function printNoticeInline(message) { + console.log(message); +} + +function isSlashCommand(line) { + if (!line || line[0] !== '/') return false; + const cmd = line.split(/\s+/)[0]; + return SLASH_COMMANDS.has(cmd); +} + readline.emitKeypressEvents(process.stdin); if (process.stdin.isTTY) process.stdin.setRawMode(true); @@ -82,6 +99,15 @@ process.stdin.on('keypress', (str, key) => { menuAbortController.abort(); } } + if (key && key.name === 'return') { + const term = String(menuSearchTerm || '').replace(/^\/+/, '').trim(); + if (term && !hasCommandMatch(term)) { + menuInjectedCommand = `/${term}`; + if (menuAbortController && !menuAbortController.signal.aborted) { + menuAbortController.abort(); + } + } + } return; } if (!isRunning && key && key.name === 'backspace') { @@ -209,12 +235,17 @@ function initReadline() { return; } - if (input.startsWith('/')) { + if (input.startsWith('/') && isSlashCommand(input)) { const result = await handleCommand(input, { rl, state, config, workspace: WORKSPACE, statusBar }); if (result && result.exit) return; promptWithStatus(); return; } + if (input.startsWith('/') && !isSlashCommand(input)) { + printNoticeInline(`无效的命令“${input}”`); + promptWithStatus(); + return; + } console.log(''); const userWriter = createIndentedWriter(' ');