feat(cli): add /agents slash command to list available agents (#16182)

This commit is contained in:
Adam Weidman
2026-01-08 16:02:44 -05:00
committed by GitHub
parent 41a8809280
commit 7e02ef697d
10 changed files with 293 additions and 0 deletions

View File

@@ -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,

View File

@@ -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} />
)}

View File

@@ -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

View 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>
);
};