diff --git a/packages/cli/src/ui/components/InputPrompt.test.tsx b/packages/cli/src/ui/components/InputPrompt.test.tsx
index c52ebf7d3c..50311fc508 100644
--- a/packages/cli/src/ui/components/InputPrompt.test.tsx
+++ b/packages/cli/src/ui/components/InputPrompt.test.tsx
@@ -789,6 +789,7 @@ describe('InputPrompt', () => {
mockSlashCommands,
mockCommandContext,
false,
+ false,
expect.any(Object),
);
@@ -816,6 +817,7 @@ describe('InputPrompt', () => {
mockSlashCommands,
mockCommandContext,
false,
+ false,
expect.any(Object),
);
@@ -843,6 +845,7 @@ describe('InputPrompt', () => {
mockSlashCommands,
mockCommandContext,
false,
+ false,
expect.any(Object),
);
@@ -870,6 +873,7 @@ describe('InputPrompt', () => {
mockSlashCommands,
mockCommandContext,
false,
+ false,
expect.any(Object),
);
@@ -897,6 +901,7 @@ describe('InputPrompt', () => {
mockSlashCommands,
mockCommandContext,
false,
+ false,
expect.any(Object),
);
@@ -925,6 +930,7 @@ describe('InputPrompt', () => {
mockSlashCommands,
mockCommandContext,
false,
+ false,
expect.any(Object),
);
@@ -952,6 +958,7 @@ describe('InputPrompt', () => {
mockSlashCommands,
mockCommandContext,
false,
+ false,
expect.any(Object),
);
@@ -980,6 +987,7 @@ describe('InputPrompt', () => {
mockSlashCommands,
mockCommandContext,
false,
+ false,
expect.any(Object),
);
@@ -1008,6 +1016,7 @@ describe('InputPrompt', () => {
mockSlashCommands,
mockCommandContext,
false,
+ false,
expect.any(Object),
);
@@ -1036,6 +1045,7 @@ describe('InputPrompt', () => {
mockSlashCommands,
mockCommandContext,
false,
+ false,
expect.any(Object),
);
@@ -1064,6 +1074,7 @@ describe('InputPrompt', () => {
mockSlashCommands,
mockCommandContext,
false,
+ false,
expect.any(Object),
);
@@ -1094,6 +1105,7 @@ describe('InputPrompt', () => {
mockSlashCommands,
mockCommandContext,
false,
+ false,
expect.any(Object),
);
@@ -1122,6 +1134,7 @@ describe('InputPrompt', () => {
mockSlashCommands,
mockCommandContext,
false,
+ false,
expect.any(Object),
);
@@ -1152,6 +1165,7 @@ describe('InputPrompt', () => {
mockSlashCommands,
mockCommandContext,
false,
+ false,
expect.any(Object),
);
@@ -1161,7 +1175,6 @@ describe('InputPrompt', () => {
describe('vim mode', () => {
it('should not call buffer.handleInput when vim mode is enabled and vim handles the input', async () => {
- props.vimModeEnabled = true;
props.vimHandleInput = vi.fn().mockReturnValue(true); // Mock that vim handled it.
const { stdin, unmount } = renderWithProviders(
,
@@ -1177,7 +1190,6 @@ describe('InputPrompt', () => {
});
it('should call buffer.handleInput when vim mode is enabled but vim does not handle the input', async () => {
- props.vimModeEnabled = true;
props.vimHandleInput = vi.fn().mockReturnValue(false); // Mock that vim did NOT handle it.
const { stdin, unmount } = renderWithProviders(
,
diff --git a/packages/cli/src/ui/components/InputPrompt.tsx b/packages/cli/src/ui/components/InputPrompt.tsx
index 35ee31e1db..10cf694b7e 100644
--- a/packages/cli/src/ui/components/InputPrompt.tsx
+++ b/packages/cli/src/ui/components/InputPrompt.tsx
@@ -155,6 +155,7 @@ export const InputPrompt: React.FC = ({
slashCommands,
commandContext,
reverseSearchActive,
+ shellModeActive,
config,
);
diff --git a/packages/cli/src/ui/hooks/useCommandCompletion.test.ts b/packages/cli/src/ui/hooks/useCommandCompletion.test.ts
index f9fbeedc3d..a900d0bbac 100644
--- a/packages/cli/src/ui/hooks/useCommandCompletion.test.ts
+++ b/packages/cli/src/ui/hooks/useCommandCompletion.test.ts
@@ -121,6 +121,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
),
);
@@ -146,6 +147,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
);
return { completion, textBuffer };
@@ -179,6 +181,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
),
);
@@ -207,6 +210,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
),
);
@@ -233,6 +237,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
),
);
@@ -246,6 +251,56 @@ describe('useCommandCompletion', () => {
);
});
});
+
+ it.each([
+ {
+ shellModeActive: false,
+ expectedSuggestions: 1,
+ expectedShowSuggestions: true,
+ description:
+ 'should show slash command suggestions when shellModeActive is false',
+ },
+ {
+ shellModeActive: true,
+ expectedSuggestions: 0,
+ expectedShowSuggestions: false,
+ description:
+ 'should not show slash command suggestions when shellModeActive is true',
+ },
+ ])(
+ '$description',
+ async ({
+ shellModeActive,
+ expectedSuggestions,
+ expectedShowSuggestions,
+ }) => {
+ setupMocks({
+ slashSuggestions: [{ label: 'clear', value: 'clear' }],
+ });
+
+ const { result } = renderHook(() => {
+ const textBuffer = useTextBufferForTest('/');
+ const completion = useCommandCompletion(
+ textBuffer,
+ testDirs,
+ testRootDir,
+ [],
+ mockCommandContext,
+ false,
+ shellModeActive, // Parameterized shellModeActive
+ mockConfig,
+ );
+ return { ...completion, textBuffer };
+ });
+
+ await waitFor(() => {
+ expect(result.current.suggestions.length).toBe(expectedSuggestions);
+ expect(result.current.showSuggestions).toBe(
+ expectedShowSuggestions,
+ );
+ });
+ },
+ );
});
describe('Navigation', () => {
@@ -272,6 +327,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
),
);
@@ -293,6 +349,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
),
);
@@ -313,6 +370,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
),
);
@@ -339,6 +397,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
),
);
@@ -368,6 +427,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
),
);
@@ -405,6 +465,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
),
);
@@ -435,6 +496,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
);
return { ...completion, textBuffer };
@@ -465,6 +527,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
);
return { ...completion, textBuffer };
@@ -498,6 +561,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
);
return { ...completion, textBuffer };
@@ -530,6 +594,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
);
return { ...completion, textBuffer };
@@ -562,6 +627,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
);
return { ...completion, textBuffer };
@@ -594,6 +660,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
);
return { ...completion, textBuffer };
@@ -619,6 +686,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
);
return { ...completion, textBuffer };
@@ -644,6 +712,7 @@ describe('useCommandCompletion', () => {
[],
mockCommandContext,
false,
+ false,
mockConfig,
);
return { ...completion, textBuffer };
diff --git a/packages/cli/src/ui/hooks/useCommandCompletion.tsx b/packages/cli/src/ui/hooks/useCommandCompletion.tsx
index b55eb89724..188c340011 100644
--- a/packages/cli/src/ui/hooks/useCommandCompletion.tsx
+++ b/packages/cli/src/ui/hooks/useCommandCompletion.tsx
@@ -51,6 +51,7 @@ export function useCommandCompletion(
slashCommands: readonly SlashCommand[],
commandContext: CommandContext,
reverseSearchActive: boolean = false,
+ shellModeActive: boolean,
config?: Config,
): UseCommandCompletionReturn {
const {
@@ -163,7 +164,7 @@ export function useCommandCompletion(
});
const slashCompletionRange = useSlashCompletion({
- enabled: completionMode === CompletionMode.SLASH,
+ enabled: completionMode === CompletionMode.SLASH && !shellModeActive,
query,
slashCommands,
commandContext,
diff --git a/packages/cli/src/ui/hooks/useGeminiStream.test.tsx b/packages/cli/src/ui/hooks/useGeminiStream.test.tsx
index 7d26187300..ffce1348bc 100644
--- a/packages/cli/src/ui/hooks/useGeminiStream.test.tsx
+++ b/packages/cli/src/ui/hooks/useGeminiStream.test.tsx
@@ -1207,6 +1207,39 @@ describe('useGeminiStream', () => {
);
});
});
+
+ it('should not call handleSlashCommand is shell mode is active', async () => {
+ const { result } = renderHook(() =>
+ useGeminiStream(
+ new MockedGeminiClientClass(mockConfig),
+ [],
+ mockAddItem,
+ mockConfig,
+ mockLoadedSettings,
+ () => {},
+ mockHandleSlashCommand,
+ true,
+ () => 'vscode' as EditorType,
+ () => {},
+ () => Promise.resolve(),
+ false,
+ () => {},
+ () => {},
+ () => {},
+ () => {},
+ 80,
+ 24,
+ ),
+ );
+
+ await act(async () => {
+ await result.current.submitQuery('/about');
+ });
+
+ await waitFor(() => {
+ expect(mockHandleSlashCommand).not.toHaveBeenCalled();
+ });
+ });
});
describe('Memory Refresh on save_memory', () => {
diff --git a/packages/cli/src/ui/hooks/useGeminiStream.ts b/packages/cli/src/ui/hooks/useGeminiStream.ts
index 5ecd615c0c..e391f6c5da 100644
--- a/packages/cli/src/ui/hooks/useGeminiStream.ts
+++ b/packages/cli/src/ui/hooks/useGeminiStream.ts
@@ -327,41 +327,43 @@ export const useGeminiStream = (
onDebugMessage(`User query: '${trimmedQuery}'`);
await logger?.logMessage(MessageSenderType.USER, trimmedQuery);
- // Handle UI-only commands first
- const slashCommandResult = isSlashCommand(trimmedQuery)
- ? await handleSlashCommand(trimmedQuery)
- : false;
+ if (!shellModeActive) {
+ // Handle UI-only commands first
+ const slashCommandResult = isSlashCommand(trimmedQuery)
+ ? await handleSlashCommand(trimmedQuery)
+ : false;
- if (slashCommandResult) {
- switch (slashCommandResult.type) {
- case 'schedule_tool': {
- const { toolName, toolArgs } = slashCommandResult;
- const toolCallRequest: ToolCallRequestInfo = {
- callId: `${toolName}-${Date.now()}-${Math.random().toString(16).slice(2)}`,
- name: toolName,
- args: toolArgs,
- isClientInitiated: true,
- prompt_id,
- };
- scheduleToolCalls([toolCallRequest], abortSignal);
- return { queryToSend: null, shouldProceed: false };
- }
- case 'submit_prompt': {
- localQueryToSendToGemini = slashCommandResult.content;
+ if (slashCommandResult) {
+ switch (slashCommandResult.type) {
+ case 'schedule_tool': {
+ const { toolName, toolArgs } = slashCommandResult;
+ const toolCallRequest: ToolCallRequestInfo = {
+ callId: `${toolName}-${Date.now()}-${Math.random().toString(16).slice(2)}`,
+ name: toolName,
+ args: toolArgs,
+ isClientInitiated: true,
+ prompt_id,
+ };
+ scheduleToolCalls([toolCallRequest], abortSignal);
+ return { queryToSend: null, shouldProceed: false };
+ }
+ case 'submit_prompt': {
+ localQueryToSendToGemini = slashCommandResult.content;
- return {
- queryToSend: localQueryToSendToGemini,
- shouldProceed: true,
- };
- }
- case 'handled': {
- return { queryToSend: null, shouldProceed: false };
- }
- default: {
- const unreachable: never = slashCommandResult;
- throw new Error(
- `Unhandled slash command result type: ${unreachable}`,
- );
+ return {
+ queryToSend: localQueryToSendToGemini,
+ shouldProceed: true,
+ };
+ }
+ case 'handled': {
+ return { queryToSend: null, shouldProceed: false };
+ }
+ default: {
+ const unreachable: never = slashCommandResult;
+ throw new Error(
+ `Unhandled slash command result type: ${unreachable}`,
+ );
+ }
}
}
}