mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-30 06:54:15 -07:00
Agent Skills: Status Bar Integration for Skill Counts (#15741)
This commit is contained in:
@@ -144,10 +144,16 @@ const createMockConfig = (overrides = {}) => ({
|
|||||||
getDebugMode: vi.fn(() => false),
|
getDebugMode: vi.fn(() => false),
|
||||||
getAccessibility: vi.fn(() => ({})),
|
getAccessibility: vi.fn(() => ({})),
|
||||||
getMcpServers: vi.fn(() => ({})),
|
getMcpServers: vi.fn(() => ({})),
|
||||||
getMcpClientManager: vi.fn().mockImplementation(() => ({
|
getToolRegistry: () => ({
|
||||||
getBlockedMcpServers: vi.fn(),
|
getTool: vi.fn(),
|
||||||
getMcpServers: vi.fn(),
|
}),
|
||||||
})),
|
getSkillManager: () => ({
|
||||||
|
getSkills: () => [],
|
||||||
|
}),
|
||||||
|
getMcpClientManager: () => ({
|
||||||
|
getMcpServers: () => ({}),
|
||||||
|
getBlockedMcpServers: () => [],
|
||||||
|
}),
|
||||||
...overrides,
|
...overrides,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ export const Composer = () => {
|
|||||||
blockedMcpServers={
|
blockedMcpServers={
|
||||||
config.getMcpClientManager()?.getBlockedMcpServers() ?? []
|
config.getMcpClientManager()?.getBlockedMcpServers() ?? []
|
||||||
}
|
}
|
||||||
|
skillCount={config.getSkillManager().getSkills().length}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -34,14 +34,16 @@ describe('<ContextSummaryDisplay />', () => {
|
|||||||
openFiles: [{ path: '/a/b/c', timestamp: Date.now() }],
|
openFiles: [{ path: '/a/b/c', timestamp: Date.now() }],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
skillCount: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should render on a single line on a wide screen', () => {
|
it('should render on a single line on a wide screen', () => {
|
||||||
const { lastFrame, unmount } = renderWithWidth(120, baseProps);
|
const { lastFrame, unmount } = renderWithWidth(120, baseProps);
|
||||||
const output = lastFrame()!;
|
const output = lastFrame()!;
|
||||||
expect(output).toContain(
|
expect(output).toContain(
|
||||||
'Using: 1 open file (ctrl+g to view) | 1 GEMINI.md file | 1 MCP server',
|
'1 open file (ctrl+g to view) | 1 GEMINI.md file | 1 MCP server | 1 skill',
|
||||||
);
|
);
|
||||||
|
expect(output).not.toContain('Using:');
|
||||||
// Check for absence of newlines
|
// Check for absence of newlines
|
||||||
expect(output.includes('\n')).toBe(false);
|
expect(output.includes('\n')).toBe(false);
|
||||||
unmount();
|
unmount();
|
||||||
@@ -51,10 +53,10 @@ describe('<ContextSummaryDisplay />', () => {
|
|||||||
const { lastFrame, unmount } = renderWithWidth(60, baseProps);
|
const { lastFrame, unmount } = renderWithWidth(60, baseProps);
|
||||||
const output = lastFrame()!;
|
const output = lastFrame()!;
|
||||||
const expectedLines = [
|
const expectedLines = [
|
||||||
' Using:',
|
' - 1 open file (ctrl+g to view)',
|
||||||
' - 1 open file (ctrl+g to view)',
|
' - 1 GEMINI.md file',
|
||||||
' - 1 GEMINI.md file',
|
' - 1 MCP server',
|
||||||
' - 1 MCP server',
|
' - 1 skill',
|
||||||
];
|
];
|
||||||
const actualLines = output.split('\n');
|
const actualLines = output.split('\n');
|
||||||
expect(actualLines).toEqual(expectedLines);
|
expect(actualLines).toEqual(expectedLines);
|
||||||
@@ -86,9 +88,10 @@ describe('<ContextSummaryDisplay />', () => {
|
|||||||
geminiMdFileCount: 0,
|
geminiMdFileCount: 0,
|
||||||
contextFileNames: [],
|
contextFileNames: [],
|
||||||
mcpServers: {},
|
mcpServers: {},
|
||||||
|
skillCount: 0,
|
||||||
};
|
};
|
||||||
const { lastFrame, unmount } = renderWithWidth(60, props);
|
const { lastFrame, unmount } = renderWithWidth(60, props);
|
||||||
const expectedLines = [' Using:', ' - 1 open file (ctrl+g to view)'];
|
const expectedLines = [' - 1 open file (ctrl+g to view)'];
|
||||||
const actualLines = lastFrame()!.split('\n');
|
const actualLines = lastFrame()!.split('\n');
|
||||||
expect(actualLines).toEqual(expectedLines);
|
expect(actualLines).toEqual(expectedLines);
|
||||||
unmount();
|
unmount();
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ interface ContextSummaryDisplayProps {
|
|||||||
mcpServers?: Record<string, MCPServerConfig>;
|
mcpServers?: Record<string, MCPServerConfig>;
|
||||||
blockedMcpServers?: Array<{ name: string; extensionName: string }>;
|
blockedMcpServers?: Array<{ name: string; extensionName: string }>;
|
||||||
ideContext?: IdeContext;
|
ideContext?: IdeContext;
|
||||||
|
skillCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ContextSummaryDisplay: React.FC<ContextSummaryDisplayProps> = ({
|
export const ContextSummaryDisplay: React.FC<ContextSummaryDisplayProps> = ({
|
||||||
@@ -25,6 +26,7 @@ export const ContextSummaryDisplay: React.FC<ContextSummaryDisplayProps> = ({
|
|||||||
mcpServers,
|
mcpServers,
|
||||||
blockedMcpServers,
|
blockedMcpServers,
|
||||||
ideContext,
|
ideContext,
|
||||||
|
skillCount,
|
||||||
}) => {
|
}) => {
|
||||||
const { columns: terminalWidth } = useTerminalSize();
|
const { columns: terminalWidth } = useTerminalSize();
|
||||||
const isNarrow = isNarrowWidth(terminalWidth);
|
const isNarrow = isNarrowWidth(terminalWidth);
|
||||||
@@ -36,7 +38,8 @@ export const ContextSummaryDisplay: React.FC<ContextSummaryDisplayProps> = ({
|
|||||||
geminiMdFileCount === 0 &&
|
geminiMdFileCount === 0 &&
|
||||||
mcpServerCount === 0 &&
|
mcpServerCount === 0 &&
|
||||||
blockedMcpServerCount === 0 &&
|
blockedMcpServerCount === 0 &&
|
||||||
openFileCount === 0
|
openFileCount === 0 &&
|
||||||
|
skillCount === 0
|
||||||
) {
|
) {
|
||||||
return <Text> </Text>; // Render an empty space to reserve height
|
return <Text> </Text>; // Render an empty space to reserve height
|
||||||
}
|
}
|
||||||
@@ -83,15 +86,23 @@ export const ContextSummaryDisplay: React.FC<ContextSummaryDisplayProps> = ({
|
|||||||
return parts.join(', ');
|
return parts.join(', ');
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const summaryParts = [openFilesText, geminiMdText, mcpText].filter(Boolean);
|
const skillText = (() => {
|
||||||
|
if (skillCount === 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return `${skillCount} skill${skillCount > 1 ? 's' : ''}`;
|
||||||
|
})();
|
||||||
|
|
||||||
|
const summaryParts = [openFilesText, geminiMdText, mcpText, skillText].filter(
|
||||||
|
Boolean,
|
||||||
|
);
|
||||||
|
|
||||||
if (isNarrow) {
|
if (isNarrow) {
|
||||||
return (
|
return (
|
||||||
<Box flexDirection="column" paddingX={1}>
|
<Box flexDirection="column" paddingX={1}>
|
||||||
<Text color={theme.text.secondary}>Using:</Text>
|
|
||||||
{summaryParts.map((part, index) => (
|
{summaryParts.map((part, index) => (
|
||||||
<Text key={index} color={theme.text.secondary}>
|
<Text key={index} color={theme.text.secondary}>
|
||||||
{' '}- {part}
|
- {part}
|
||||||
</Text>
|
</Text>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
@@ -100,9 +111,7 @@ export const ContextSummaryDisplay: React.FC<ContextSummaryDisplayProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box paddingX={1}>
|
<Box paddingX={1}>
|
||||||
<Text color={theme.text.secondary}>
|
<Text color={theme.text.secondary}>{summaryParts.join(' | ')}</Text>
|
||||||
Using: {summaryParts.join(' | ')}
|
|
||||||
</Text>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user