mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-18 09:11:55 -07:00
feat(ui): improve discoverability of MCP slash commands (#6080)
Co-authored-by: Rinil Kunhiraman <rinilkunhiraman@users.noreply.github.com> Co-authored-by: Allen Hutchison <adh@google.com>
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
import type React from 'react';
|
||||
import { Box, Text } from 'ink';
|
||||
import { Colors } from '../colors.js';
|
||||
import type { SlashCommand } from '../commands/types.js';
|
||||
import { type SlashCommand, CommandKind } from '../commands/types.js';
|
||||
|
||||
interface Help {
|
||||
commands: readonly SlashCommand[];
|
||||
@@ -64,27 +64,32 @@ export const Help: React.FC<Help> = ({ commands }) => (
|
||||
<Text bold color={Colors.Foreground}>
|
||||
Commands:
|
||||
</Text>
|
||||
{commands.map((command: SlashCommand) => (
|
||||
<Box key={command.name} flexDirection="column">
|
||||
<Text color={Colors.Foreground}>
|
||||
<Text bold color={Colors.AccentPurple}>
|
||||
{' '}
|
||||
/{command.name}
|
||||
</Text>
|
||||
{command.description && ' - ' + command.description}
|
||||
</Text>
|
||||
{command.subCommands &&
|
||||
command.subCommands.map((subCommand) => (
|
||||
<Text key={subCommand.name} color={Colors.Foreground}>
|
||||
<Text bold color={Colors.AccentPurple}>
|
||||
{' '}
|
||||
{subCommand.name}
|
||||
</Text>
|
||||
{subCommand.description && ' - ' + subCommand.description}
|
||||
{commands
|
||||
.filter((command) => command.description)
|
||||
.map((command: SlashCommand) => (
|
||||
<Box key={command.name} flexDirection="column">
|
||||
<Text color={Colors.Foreground}>
|
||||
<Text bold color={Colors.AccentPurple}>
|
||||
{' '}
|
||||
/{command.name}
|
||||
</Text>
|
||||
))}
|
||||
</Box>
|
||||
))}
|
||||
{command.kind === CommandKind.MCP_PROMPT && (
|
||||
<Text color={Colors.Gray}> [MCP]</Text>
|
||||
)}
|
||||
{command.description && ' - ' + command.description}
|
||||
</Text>
|
||||
{command.subCommands &&
|
||||
command.subCommands.map((subCommand) => (
|
||||
<Text key={subCommand.name} color={Colors.Foreground}>
|
||||
<Text bold color={Colors.AccentPurple}>
|
||||
{' '}
|
||||
{subCommand.name}
|
||||
</Text>
|
||||
{subCommand.description && ' - ' + subCommand.description}
|
||||
</Text>
|
||||
))}
|
||||
</Box>
|
||||
))}
|
||||
<Text color={Colors.Foreground}>
|
||||
<Text bold color={Colors.AccentPurple}>
|
||||
{' '}
|
||||
@@ -92,6 +97,10 @@ export const Help: React.FC<Help> = ({ commands }) => (
|
||||
</Text>
|
||||
- shell command
|
||||
</Text>
|
||||
<Text color={Colors.Foreground}>
|
||||
<Text color={Colors.Gray}>[MCP]</Text> - Model Context Protocol command
|
||||
(from external servers)
|
||||
</Text>
|
||||
|
||||
<Box height={1} />
|
||||
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
import { Box, Text } from 'ink';
|
||||
import { Colors } from '../colors.js';
|
||||
import { PrepareLabel } from './PrepareLabel.js';
|
||||
import { isSlashCommand } from '../utils/commandUtils.js';
|
||||
import { CommandKind } from '../commands/types.js';
|
||||
export interface Suggestion {
|
||||
label: string;
|
||||
value: string;
|
||||
description?: string;
|
||||
matchedIndex?: number;
|
||||
commandKind?: CommandKind;
|
||||
}
|
||||
interface SuggestionsDisplayProps {
|
||||
suggestions: Suggestion[];
|
||||
@@ -53,21 +54,6 @@ export function SuggestionsDisplay({
|
||||
);
|
||||
const visibleSuggestions = suggestions.slice(startIndex, endIndex);
|
||||
|
||||
const isSlashCommandMode = isSlashCommand(userInput);
|
||||
let commandNameWidth = 0;
|
||||
|
||||
if (isSlashCommandMode) {
|
||||
const maxLabelLength = visibleSuggestions.length
|
||||
? Math.max(...visibleSuggestions.map((s) => s.label.length))
|
||||
: 0;
|
||||
|
||||
const maxAllowedWidth = Math.floor(width * 0.35);
|
||||
commandNameWidth = Math.max(
|
||||
15,
|
||||
Math.min(maxLabelLength + 2, maxAllowedWidth),
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" paddingX={1} width={width}>
|
||||
{scrollOffset > 0 && <Text color={Colors.Foreground}>▲</Text>}
|
||||
@@ -88,31 +74,33 @@ export function SuggestionsDisplay({
|
||||
return (
|
||||
<Box key={`${suggestion.value}-${originalIndex}`} width={width}>
|
||||
<Box flexDirection="row">
|
||||
{isSlashCommandMode ? (
|
||||
<>
|
||||
<Box width={commandNameWidth} flexShrink={0}>
|
||||
{labelElement}
|
||||
</Box>
|
||||
{suggestion.description ? (
|
||||
<Box flexGrow={1} marginLeft={1}>
|
||||
<Text color={textColor} wrap="wrap">
|
||||
{suggestion.description}
|
||||
</Text>
|
||||
</Box>
|
||||
) : null}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{labelElement}
|
||||
{suggestion.description ? (
|
||||
<Box flexGrow={1} marginLeft={1}>
|
||||
<Text color={textColor} wrap="wrap">
|
||||
{suggestion.description}
|
||||
</Text>
|
||||
</Box>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
{(() => {
|
||||
const isSlashCommand = userInput.startsWith('/');
|
||||
return (
|
||||
<>
|
||||
{isSlashCommand ? (
|
||||
<Box flexShrink={0} paddingRight={2}>
|
||||
{labelElement}
|
||||
{suggestion.commandKind === CommandKind.MCP_PROMPT && (
|
||||
<Text color={Colors.Gray}> [MCP]</Text>
|
||||
)}
|
||||
</Box>
|
||||
) : (
|
||||
labelElement
|
||||
)}
|
||||
{suggestion.description && (
|
||||
<Box
|
||||
flexGrow={1}
|
||||
paddingLeft={isSlashCommand ? undefined : 1}
|
||||
>
|
||||
<Text color={textColor} wrap="truncate">
|
||||
{suggestion.description}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user