mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-21 11:30:38 -07:00
feat(cli): add /agents slash command to list available agents (#16182)
This commit is contained in:
@@ -71,6 +71,30 @@ describe('<HistoryItemDisplay />', () => {
|
||||
},
|
||||
);
|
||||
|
||||
it('renders AgentsStatus for "agents_list" type', () => {
|
||||
const item: HistoryItem = {
|
||||
...baseItem,
|
||||
type: MessageType.AGENTS_LIST,
|
||||
agents: [
|
||||
{
|
||||
name: 'local_agent',
|
||||
displayName: 'Local Agent',
|
||||
description: ' Local agent description.\n Second line.',
|
||||
kind: 'local',
|
||||
},
|
||||
{
|
||||
name: 'remote_agent',
|
||||
description: 'Remote agent description.',
|
||||
kind: 'remote',
|
||||
},
|
||||
],
|
||||
};
|
||||
const { lastFrame } = renderWithProviders(
|
||||
<HistoryItemDisplay {...baseItem} item={item} />,
|
||||
);
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders StatsDisplay for "stats" type', () => {
|
||||
const item: HistoryItem = {
|
||||
...baseItem,
|
||||
|
||||
@@ -29,6 +29,7 @@ import { ExtensionsList } from './views/ExtensionsList.js';
|
||||
import { getMCPServerStatus } from '@google/gemini-cli-core';
|
||||
import { ToolsList } from './views/ToolsList.js';
|
||||
import { SkillsList } from './views/SkillsList.js';
|
||||
import { AgentsStatus } from './views/AgentsStatus.js';
|
||||
import { McpStatus } from './views/McpStatus.js';
|
||||
import { ChatList } from './views/ChatList.js';
|
||||
import { HooksList } from './views/HooksList.js';
|
||||
@@ -160,6 +161,12 @@ export const HistoryItemDisplay: React.FC<HistoryItemDisplayProps> = ({
|
||||
showDescriptions={itemForDisplay.showDescriptions}
|
||||
/>
|
||||
)}
|
||||
{itemForDisplay.type === 'agents_list' && (
|
||||
<AgentsStatus
|
||||
agents={itemForDisplay.agents}
|
||||
terminalWidth={terminalWidth}
|
||||
/>
|
||||
)}
|
||||
{itemForDisplay.type === 'mcp_status' && (
|
||||
<McpStatus {...itemForDisplay} serverStatus={getMCPServerStatus} />
|
||||
)}
|
||||
|
||||
@@ -352,6 +352,21 @@ exports[`<HistoryItemDisplay /> > gemini items (alternateBuffer=true) > should r
|
||||
50 Line 50"
|
||||
`;
|
||||
|
||||
exports[`<HistoryItemDisplay /> > renders AgentsStatus for "agents_list" type 1`] = `
|
||||
"Local Agents
|
||||
|
||||
- Local Agent (local_agent)
|
||||
Local agent description.
|
||||
Second line.
|
||||
|
||||
Remote Agents
|
||||
|
||||
- remote_agent
|
||||
Remote agent description.
|
||||
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`<HistoryItemDisplay /> > renders InfoMessage for "info" type with multi-line text (alternateBuffer=false) 1`] = `
|
||||
"
|
||||
ℹ ⚡ Line 1
|
||||
|
||||
72
packages/cli/src/ui/components/views/AgentsStatus.tsx
Normal file
72
packages/cli/src/ui/components/views/AgentsStatus.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { Box, Text } from 'ink';
|
||||
import type React from 'react';
|
||||
import { theme } from '../../semantic-colors.js';
|
||||
import type { AgentDefinitionJson } from '../../types.js';
|
||||
import { MarkdownDisplay } from '../../utils/MarkdownDisplay.js';
|
||||
|
||||
interface AgentsStatusProps {
|
||||
agents: AgentDefinitionJson[];
|
||||
terminalWidth: number;
|
||||
}
|
||||
|
||||
export const AgentsStatus: React.FC<AgentsStatusProps> = ({
|
||||
agents,
|
||||
terminalWidth,
|
||||
}) => {
|
||||
const localAgents = agents.filter((a) => a.kind === 'local');
|
||||
const remoteAgents = agents.filter((a) => a.kind === 'remote');
|
||||
|
||||
if (agents.length === 0) {
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text>No agents available.</Text>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
const renderAgentList = (title: string, agentList: AgentDefinitionJson[]) => {
|
||||
if (agentList.length === 0) return null;
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" marginBottom={1}>
|
||||
<Text bold color={theme.text.primary}>
|
||||
{title}
|
||||
</Text>
|
||||
<Box height={1} />
|
||||
{agentList.map((agent) => (
|
||||
<Box key={agent.name} flexDirection="row">
|
||||
<Text color={theme.text.primary}>{' '}- </Text>
|
||||
<Box flexDirection="column">
|
||||
<Text bold color={theme.text.accent}>
|
||||
{agent.displayName || agent.name}
|
||||
{agent.displayName && agent.displayName !== agent.name && (
|
||||
<Text bold={false}> ({agent.name})</Text>
|
||||
)}
|
||||
</Text>
|
||||
{agent.description && (
|
||||
<MarkdownDisplay
|
||||
terminalWidth={terminalWidth}
|
||||
text={agent.description}
|
||||
isPending={false}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" marginBottom={1}>
|
||||
{renderAgentList('Local Agents', localAgents)}
|
||||
{renderAgentList('Remote Agents', remoteAgents)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user