mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-28 22:14:52 -07:00
feat(cli): refine dense output for ListDirectory and ReadManyFiles results
This commit is contained in:
@@ -229,33 +229,35 @@ describe('DenseToolMessage', () => {
|
|||||||
|
|
||||||
it('renders correctly for ls results', () => {
|
it('renders correctly for ls results', () => {
|
||||||
const lsResult = {
|
const lsResult = {
|
||||||
summary: 'Listed 2 files',
|
summary: 'Listed 2 files. (1 ignored)',
|
||||||
files: ['file1.ts', 'dir1'],
|
files: ['file1.ts', 'dir1'],
|
||||||
};
|
};
|
||||||
const { lastFrame } = renderWithProviders(
|
const { lastFrame } = renderWithProviders(
|
||||||
<DenseToolMessage {...defaultProps} resultDisplay={lsResult} />,
|
<DenseToolMessage {...defaultProps} resultDisplay={lsResult} />,
|
||||||
);
|
);
|
||||||
const output = lastFrame();
|
const output = lastFrame();
|
||||||
expect(output).toContain('→ Listed 2 files');
|
expect(output).toContain('→ Listed 2 files. (1 ignored)');
|
||||||
expect(output).toContain('file1.ts');
|
// Directory listings should not have a payload in dense mode
|
||||||
expect(output).toContain('dir1');
|
expect(output).not.toContain('file1.ts');
|
||||||
|
expect(output).not.toContain('dir1');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders correctly for ReadManyFiles results', () => {
|
it('renders correctly for ReadManyFiles results', () => {
|
||||||
const rmfResult = {
|
const rmfResult = {
|
||||||
summary: 'Read 3 file(s)',
|
summary: 'Read 3 file(s)',
|
||||||
files: ['file1.ts', 'file2.ts', 'file3.ts'],
|
files: ['file1.ts', 'file2.ts', 'file3.ts'],
|
||||||
|
include: ['**/*.ts'],
|
||||||
skipped: [{ path: 'skipped.bin', reason: 'binary' }],
|
skipped: [{ path: 'skipped.bin', reason: 'binary' }],
|
||||||
};
|
};
|
||||||
const { lastFrame } = renderWithProviders(
|
const { lastFrame } = renderWithProviders(
|
||||||
<DenseToolMessage {...defaultProps} resultDisplay={rmfResult} />,
|
<DenseToolMessage {...defaultProps} resultDisplay={rmfResult} />,
|
||||||
);
|
);
|
||||||
const output = lastFrame();
|
const output = lastFrame();
|
||||||
expect(output).toContain('→ Read 3 file(s)');
|
expect(output).toContain('Attempting to read files from **/*.ts');
|
||||||
|
expect(output).toContain('→ Read 3 file(s) (1 ignored)');
|
||||||
expect(output).toContain('file1.ts');
|
expect(output).toContain('file1.ts');
|
||||||
expect(output).toContain('file2.ts');
|
expect(output).toContain('file2.ts');
|
||||||
expect(output).toContain('file3.ts');
|
expect(output).toContain('file3.ts');
|
||||||
expect(output).toContain('(1 skipped)');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders correctly for todo updates', () => {
|
it('renders correctly for todo updates', () => {
|
||||||
|
|||||||
@@ -144,44 +144,30 @@ function getFileOpData(
|
|||||||
return { description, summary, payload };
|
return { description, summary, payload };
|
||||||
}
|
}
|
||||||
|
|
||||||
function getListResultData(
|
function getReadManyFilesData(result: ReadManyFilesResult): ViewParts {
|
||||||
result: ListDirectoryResult | ReadManyFilesResult,
|
const items = result.files ?? [];
|
||||||
toolName: string,
|
|
||||||
originalDescription?: string,
|
|
||||||
): ViewParts {
|
|
||||||
let description = originalDescription;
|
|
||||||
const items: string[] = result.files ?? [];
|
|
||||||
const maxVisible = 10;
|
const maxVisible = 10;
|
||||||
|
const includePatterns = result.include?.join(', ') ?? '';
|
||||||
|
const description = `Attempting to read files from ${includePatterns}`;
|
||||||
|
|
||||||
// Enhance with ReadManyFiles specific data if present
|
const skippedCount = result.skipped?.length ?? 0;
|
||||||
const rmf = result as ReadManyFilesResult;
|
const summaryStr = `Read ${items.length} file(s)${
|
||||||
if (toolName === 'ReadManyFiles' && rmf.include) {
|
skippedCount > 0 ? ` (${skippedCount} ignored)` : ''
|
||||||
const includePatterns = rmf.include.join(', ');
|
}`;
|
||||||
description = `Attempting to read files from ${includePatterns}`;
|
const summary = <Text color={theme.text.accent}>→ {summaryStr}</Text>;
|
||||||
result.summary = `Read ${items.length} file(s)`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const summary = <Text color={theme.text.accent}>→ {result.summary}</Text>;
|
|
||||||
|
|
||||||
const skippedCount = rmf.skipped?.length ?? 0;
|
|
||||||
const skippedText =
|
|
||||||
skippedCount > 0 ? `(${skippedCount} skipped)` : undefined;
|
|
||||||
|
|
||||||
const excludedText =
|
const excludedText =
|
||||||
rmf.excludes && rmf.excludes.length > 0
|
result.excludes && result.excludes.length > 0
|
||||||
? `Excluded patterns: ${rmf.excludes.slice(0, 3).join(', ')}${rmf.excludes.length > 3 ? '...' : ''}`
|
? `Excluded patterns: ${result.excludes.slice(0, 3).join(', ')}${
|
||||||
|
result.excludes.length > 3 ? '...' : ''
|
||||||
|
}`
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const hasItems = items.length > 0;
|
const hasItems = items.length > 0;
|
||||||
const payload =
|
const payload =
|
||||||
hasItems || skippedText || excludedText ? (
|
hasItems || excludedText ? (
|
||||||
<Box flexDirection="column" marginLeft={2}>
|
<Box flexDirection="column" marginLeft={2}>
|
||||||
{hasItems && <RenderItemsList items={items} maxVisible={maxVisible} />}
|
{hasItems && <RenderItemsList items={items} maxVisible={maxVisible} />}
|
||||||
{skippedText && (
|
|
||||||
<Text color={theme.text.secondary} dimColor>
|
|
||||||
{skippedText}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
{excludedText && (
|
{excludedText && (
|
||||||
<Text color={theme.text.secondary} dimColor>
|
<Text color={theme.text.secondary} dimColor>
|
||||||
{excludedText}
|
{excludedText}
|
||||||
@@ -193,6 +179,30 @@ function getListResultData(
|
|||||||
return { description, summary, payload };
|
return { description, summary, payload };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getListDirectoryData(
|
||||||
|
result: ListDirectoryResult,
|
||||||
|
originalDescription?: string,
|
||||||
|
): ViewParts {
|
||||||
|
const summary = <Text color={theme.text.accent}>→ {result.summary}</Text>;
|
||||||
|
// For directory listings, we want NO payload in dense mode as per request
|
||||||
|
return { description: originalDescription, summary, payload: undefined };
|
||||||
|
}
|
||||||
|
|
||||||
|
function getListResultData(
|
||||||
|
result: ListDirectoryResult | ReadManyFilesResult,
|
||||||
|
toolName: string,
|
||||||
|
originalDescription?: string,
|
||||||
|
): ViewParts {
|
||||||
|
// Use 'include' to determine if this is a ReadManyFilesResult
|
||||||
|
if ('include' in result) {
|
||||||
|
return getReadManyFilesData(result);
|
||||||
|
}
|
||||||
|
return getListDirectoryData(
|
||||||
|
result as ListDirectoryResult,
|
||||||
|
originalDescription,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function getGenericSuccessData(
|
function getGenericSuccessData(
|
||||||
resultDisplay: unknown,
|
resultDisplay: unknown,
|
||||||
originalDescription?: string,
|
originalDescription?: string,
|
||||||
|
|||||||
Reference in New Issue
Block a user