fix(cli): treat unknown slash commands as regular input instead of showing error (#17393)

Co-authored-by: Tommaso Sciortino <sciortino@gmail.com>
This commit is contained in:
skyvanguard
2026-02-18 18:52:51 -03:00
committed by GitHub
parent e7f97dfa44
commit 178388d931
2 changed files with 74 additions and 35 deletions

View File

@@ -20,6 +20,7 @@ import {
type GeminiClient,
type UserFeedbackPayload,
SlashCommandStatus,
MCPDiscoveryState,
makeFakeConfig,
coreEvents,
CoreEvent,
@@ -389,21 +390,49 @@ describe('useSlashCommandProcessor', () => {
});
describe('Command Execution Logic', () => {
it('should display an error for an unknown command', async () => {
it('should treat unknown commands as regular input', async () => {
const result = await setupProcessorHook();
await waitFor(() => expect(result.current.slashCommands).toBeDefined());
let handled: Awaited<
ReturnType<typeof result.current.handleSlashCommand>
>;
await act(async () => {
await result.current.handleSlashCommand('/nonexistent');
handled = await result.current.handleSlashCommand('/nonexistent');
});
// Expect 2 calls: one for the user's input, one for the error message.
expect(mockAddItem).toHaveBeenCalledTimes(2);
expect(mockAddItem).toHaveBeenLastCalledWith(
{
// Unknown commands should return false so the input is sent to the model
expect(handled!).toBe(false);
// Should not add anything to history (the regular flow will handle it)
expect(mockAddItem).not.toHaveBeenCalled();
});
it('should show MCP loading warning for unknown commands when MCP is loading', async () => {
vi.spyOn(mockConfig, 'getMcpClientManager').mockReturnValue({
getDiscoveryState: () => MCPDiscoveryState.IN_PROGRESS,
} as ReturnType<typeof mockConfig.getMcpClientManager>);
const result = await setupProcessorHook();
await waitFor(() => expect(result.current.slashCommands).toBeDefined());
let handled: Awaited<
ReturnType<typeof result.current.handleSlashCommand>
>;
await act(async () => {
handled = await result.current.handleSlashCommand('/mcp-command');
});
// When MCP is loading, should handle the command (show warning)
expect(handled!).not.toBe(false);
// Should add user input and error message to history
expect(mockAddItem).toHaveBeenCalledWith(
{ type: MessageType.USER, text: '/mcp-command' },
expect.any(Number),
);
expect(mockAddItem).toHaveBeenCalledWith(
expect.objectContaining({
type: MessageType.ERROR,
text: 'Unknown command: /nonexistent',
},
}),
expect.any(Number),
);
});
@@ -769,19 +798,17 @@ describe('useSlashCommandProcessor', () => {
});
await waitFor(() => expect(result.current.slashCommands).toHaveLength(1));
let handled: Awaited<
ReturnType<typeof result.current.handleSlashCommand>
>;
await act(async () => {
// Use uppercase when command is lowercase
await result.current.handleSlashCommand('/Test');
handled = await result.current.handleSlashCommand('/Test');
});
// It should fail and call addItem with an error
expect(mockAddItem).toHaveBeenCalledWith(
{
type: MessageType.ERROR,
text: 'Unknown command: /Test',
},
expect.any(Number),
);
// Case mismatch means it's not a known command, so treat as regular input
expect(handled!).toBe(false);
expect(mockAddItem).not.toHaveBeenCalled();
});
it('should correctly match an altName', async () => {

View File

@@ -362,6 +362,36 @@ export const useSlashCommandProcessor = (
return false;
}
const {
commandToExecute,
args,
canonicalPath: resolvedCommandPath,
} = parseSlashCommand(trimmed, commands);
// If the input doesn't match any known command, check if MCP servers
// are still loading (the command might come from an MCP server).
// Otherwise, treat it as regular text input (e.g. file paths like
// /home/user/file.txt) and let it be sent to the model.
if (!commandToExecute) {
const isMcpLoading =
config?.getMcpClientManager()?.getDiscoveryState() ===
MCPDiscoveryState.IN_PROGRESS;
if (isMcpLoading) {
setIsProcessing(true);
if (addToHistory) {
addItem({ type: MessageType.USER, text: trimmed }, Date.now());
}
addMessage({
type: MessageType.ERROR,
content: `Unknown command: ${trimmed}. Command might have been from an MCP server but MCP servers are not done loading.`,
timestamp: new Date(),
});
setIsProcessing(false);
return { type: 'handled' };
}
return false;
}
setIsProcessing(true);
if (addToHistory) {
@@ -373,11 +403,6 @@ export const useSlashCommandProcessor = (
}
let hasError = false;
const {
commandToExecute,
args,
canonicalPath: resolvedCommandPath,
} = parseSlashCommand(trimmed, commands);
const subcommand =
resolvedCommandPath.length > 1
@@ -654,19 +679,6 @@ export const useSlashCommandProcessor = (
}
}
const isMcpLoading =
config?.getMcpClientManager()?.getDiscoveryState() ===
MCPDiscoveryState.IN_PROGRESS;
const errorMessage = isMcpLoading
? `Unknown command: ${trimmed}. Command might have been from an MCP server but MCP servers are not done loading.`
: `Unknown command: ${trimmed}`;
addMessage({
type: MessageType.ERROR,
content: errorMessage,
timestamp: new Date(),
});
return { type: 'handled' };
} catch (e: unknown) {
hasError = true;