feat(cli): introduce visualize tool for rich data display

- Implement `visualize` tool in core to support tables, charts, and diffs.
- Add `RichDataDisplay` UI component using Ink for rendering visualizations.
- Integrate visualization support into `ToolResultDisplay`.
- Update system prompts to encourage the use of the `visualize` tool for structured data.
- Add `info` semantic color to themes.
- Fix shell parser initialization in tests.
This commit is contained in:
Bryan Morgan
2026-02-10 19:53:38 -05:00
parent 4a48d7cf93
commit 545a23f120
18 changed files with 1133 additions and 20 deletions
@@ -112,6 +112,7 @@ describe('<Header />', () => {
error: '',
success: '',
warning: '',
info: '',
},
});
const Gradient = await import('ink-gradient');
@@ -0,0 +1,129 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { renderWithProviders } from '../../../test-utils/render.js';
import { RichDataDisplay } from './RichDataDisplay.js';
import { describe, it, expect } from 'vitest';
describe('RichDataDisplay', () => {
it('should render table visualization', () => {
const data = {
type: 'table' as const,
data: [{ name: 'Test', value: 123 }],
};
const { lastFrame } = renderWithProviders(
<RichDataDisplay data={data} availableWidth={80} />,
);
const output = lastFrame();
expect(output).toContain('name');
expect(output).toContain('value');
expect(output).toContain('Test');
expect(output).toContain('123');
});
it('should render bar chart visualization', () => {
const data = {
type: 'bar_chart' as const,
title: 'Sales',
data: [
{ label: 'Q1', value: 10 },
{ label: 'Q2', value: 20 },
],
};
const { lastFrame } = renderWithProviders(
<RichDataDisplay data={data} availableWidth={80} />,
);
const output = lastFrame();
expect(output).toContain('Sales');
expect(output).toContain('Q1');
expect(output).toContain('Q2');
expect(output).toContain('█'); // Check for bar character
});
it('should render line chart visualization', () => {
const data = {
type: 'line_chart' as const,
title: 'Trends',
data: [
{ label: 'Jan', value: 10 },
{ label: 'Feb', value: 20 },
{ label: 'Mar', value: 15 },
],
};
const { lastFrame } = renderWithProviders(
<RichDataDisplay data={data} availableWidth={80} />,
);
const output = lastFrame();
expect(output).toContain('Trends');
expect(output).toContain('Jan');
expect(output).toContain('Feb');
expect(output).toContain('Mar');
expect(output).toContain('•'); // Check for plot point
expect(output).toContain('│'); // Check for axis
});
it('should render pie chart visualization', () => {
const data = {
type: 'pie_chart' as const,
title: 'Market Share',
data: [
{ label: 'A', value: 50 },
{ label: 'B', value: 50 },
],
};
const { lastFrame } = renderWithProviders(
<RichDataDisplay data={data} availableWidth={80} />,
);
const output = lastFrame();
expect(output).toContain('Market Share');
expect(output).toContain('A');
expect(output).toContain('B');
expect(output).toContain('50.0%');
expect(output).toContain('█'); // Check for proportional bar
});
it('should show saved file path', () => {
const data = {
type: 'table' as const,
data: [],
savedFilePath: '/path/to/file.csv',
};
const { lastFrame } = renderWithProviders(
<RichDataDisplay data={data} availableWidth={80} />,
);
const output = lastFrame();
expect(output).toContain('Saved to: /path/to/file.csv');
});
it('should render diff visualization', () => {
const data = {
type: 'diff' as const,
data: {
fileDiff:
'diff --git a/file.txt b/file.txt\nindex 123..456 100644\n--- a/file.txt\n+++ b/file.txt\n@@ -1 +1 @@\n-foo\n+bar',
fileName: 'file.txt',
},
};
const { lastFrame } = renderWithProviders(
<RichDataDisplay data={data} availableWidth={80} />,
);
const output = lastFrame();
expect(output).toContain('foo');
expect(output).toContain('bar');
});
});
@@ -0,0 +1,321 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import type React from 'react';
import { Box, Text } from 'ink';
import { theme } from '../../semantic-colors.js';
import { Table, type Column } from '../Table.js';
import { DiffRenderer } from './DiffRenderer.js';
import * as Diff from 'diff';
import type { RichVisualization } from '@google/gemini-cli-core';
import { getPlainTextLength } from '../../utils/InlineMarkdownRenderer.js';
interface RichDataDisplayProps {
data: RichVisualization;
availableWidth: number;
}
export const RichDataDisplay: React.FC<RichDataDisplayProps> = ({
data,
availableWidth,
}) => {
const {
type,
title,
data: rawData,
columns: providedColumns,
savedFilePath,
} = data;
const normalizeData = (
data: unknown[],
providedCols: typeof providedColumns,
) =>
data.map((item) => {
const record = item as Record<string, unknown>;
let label = 'Unknown';
let value = 0;
if (providedCols && providedCols.length >= 2) {
label = String(record[providedCols[0].key]);
value = Number(record[providedCols[1].key]);
} else {
// Auto-detect
const keys = Object.keys(record);
const labelKey =
keys.find((k) => typeof record[k] === 'string') || keys[0];
const valueKey = keys.find((k) => typeof record[k] === 'number');
if (labelKey) label = String(record[labelKey]);
if (valueKey) value = Number(record[valueKey]);
}
return { label, value };
});
const renderContent = () => {
if (type === 'table' && Array.isArray(rawData)) {
const tableData = rawData as Array<Record<string, unknown>>;
// Infer columns if not provided
let columns: Array<Column<Record<string, unknown>>> = [];
if (providedColumns) {
columns = providedColumns.map((col) => ({
key: col.key,
header: col.label,
}));
} else if (tableData.length > 0) {
columns = Object.keys(tableData[0]).map((key) => ({
key,
header: key,
}));
}
// Calculate widths based on content
const paddingPerCol = 2; // Extra buffer
const columnContentWidths = columns.map((col) => {
const headerWidth = getPlainTextLength(String(col.header));
const maxDataWidth = Math.max(
...tableData.map((row) =>
getPlainTextLength(String(row[col.key] || '')),
),
0,
);
return Math.max(headerWidth, maxDataWidth) + paddingPerCol;
});
const totalContentWidth = columnContentWidths.reduce((a, b) => a + b, 0);
if (totalContentWidth > availableWidth && columns.length > 0) {
// Scale down if exceeds available width
const scaleFactor = availableWidth / totalContentWidth;
columns = columns.map((col, i) => ({
...col,
width: Math.max(4, Math.floor(columnContentWidths[i] * scaleFactor)),
}));
} else {
// Use content widths or distribute remaining space
columns = columns.map((col, i) => ({
...col,
width: columnContentWidths[i],
}));
}
return <Table data={tableData} columns={columns} />;
} else if (type === 'bar_chart' && Array.isArray(rawData)) {
const normalized = normalizeData(rawData as unknown[], providedColumns);
const maxValue = Math.max(...normalized.map((d) => d.value), 1);
const maxLabelLen = Math.max(...normalized.map((d) => d.label.length), 1);
const barAreaWidth = Math.max(10, availableWidth - maxLabelLen - 10);
return (
<Box flexDirection="column">
{normalized.map((item, i) => {
const barLen = Math.max(
0,
Math.floor((item.value / maxValue) * barAreaWidth),
);
const bar = '█'.repeat(barLen);
return (
<Box key={i}>
<Text>{item.label.padEnd(maxLabelLen + 1)}</Text>
<Text color={theme.text.accent}>{bar}</Text>
<Text> {item.value}</Text>
</Box>
);
})}
</Box>
);
} else if (type === 'line_chart' && Array.isArray(rawData)) {
const normalized = normalizeData(rawData as unknown[], providedColumns);
if (normalized.length === 0) return <Text>No data to display.</Text>;
const maxValue = Math.max(...normalized.map((d) => d.value), 0);
const minValue = Math.min(...normalized.map((d) => d.value), 0);
const range = Math.max(maxValue - minValue, 1);
const chartHeight = 10;
// Plotting
const rows: string[][] = Array.from({ length: chartHeight }, () =>
Array.from({ length: normalized.length }, () => ' '),
);
normalized.forEach((item, x) => {
const y = Math.min(
chartHeight - 1,
Math.max(
0,
Math.floor(((item.value - minValue) / range) * (chartHeight - 1)),
),
);
rows[chartHeight - 1 - y][x] = '•';
});
return (
<Box flexDirection="column" marginTop={1}>
{rows.map((row, i) => {
const yValue =
minValue + (range * (chartHeight - 1 - i)) / (chartHeight - 1);
return (
<Box key={i}>
<Text color={theme.text.secondary} dimColor>
{yValue.toFixed(1).padStart(8)}
</Text>
<Text color={theme.text.accent}>{row.join(' ')}</Text>
</Box>
);
})}
<Box marginLeft={10}>
<Text color={theme.text.secondary} dimColor>
{'──'.repeat(normalized.length)}
</Text>
</Box>
<Box marginLeft={10}>
{normalized.map((item, i) => (
<Box key={i} width={3}>
<Text color={theme.text.secondary} dimColor wrap="truncate-end">
{item.label}
</Text>
</Box>
))}
</Box>
</Box>
);
} else if (type === 'pie_chart' && Array.isArray(rawData)) {
const normalized = normalizeData(rawData as unknown[], providedColumns);
const total = normalized.reduce((sum, item) => sum + item.value, 0);
const colors = [
theme.text.accent,
theme.status.success,
theme.status.warning,
theme.status.info,
'#FF6B6B',
'#4D96FF',
'#6BCB77',
'#FFD93D',
];
return (
<Box flexDirection="column" marginTop={1}>
{/* Proportional Bar */}
<Box height={1} marginBottom={1}>
{normalized.map((item, i) => {
const percent = total > 0 ? item.value / total : 0;
const barWidth = Math.max(
1,
Math.floor(percent * availableWidth),
);
return (
<Text key={i} color={colors[i % colors.length]}>
{'█'.repeat(barWidth)}
</Text>
);
})}
</Box>
{/* Legend */}
{normalized.map((item, i) => {
const percent = total > 0 ? (item.value / total) * 100 : 0;
return (
<Box key={i}>
<Text color={colors[i % colors.length]}> </Text>
<Text bold>{item.label}: </Text>
<Text>{item.value} </Text>
<Text color={theme.text.secondary}>
({percent.toFixed(1)}%)
</Text>
</Box>
);
})}
</Box>
);
} else if (
type === 'diff' &&
(typeof rawData === 'object' || typeof rawData === 'string') &&
rawData
) {
let diffContent: string | undefined;
let filename = 'Diff';
if (typeof rawData === 'string') {
diffContent = rawData;
} else {
const diffData = rawData as {
fileDiff?: string;
fileName?: string;
old?: string;
new?: string;
oldContent?: string;
newContent?: string;
originalContent?: string;
};
diffContent = diffData.fileDiff;
filename = diffData.fileName || 'Diff';
if (!diffContent) {
const oldVal =
diffData.old ?? diffData.oldContent ?? diffData.originalContent;
const newVal = diffData.new ?? diffData.newContent;
if (oldVal !== undefined && newVal !== undefined) {
diffContent = Diff.createPatch(
filename,
String(oldVal),
String(newVal),
);
}
}
}
if (diffContent) {
return (
<DiffRenderer
diffContent={diffContent}
filename={filename}
availableTerminalHeight={20} // Reasonable default or pass from props
terminalWidth={availableWidth}
/>
);
} else {
return (
<Box flexDirection="column">
<Text color={theme.status.error}>
Error: Diff data missing &apos;fileDiff&apos; property.
</Text>
<Text color={theme.text.secondary} dimColor>
Expected data to be a string or an object with
&apos;fileDiff&apos;, or both &apos;old&apos; and &apos;new&apos;
content.
</Text>
<Text color={theme.text.secondary} dimColor>
Received keys:{' '}
{typeof rawData === 'object'
? Object.keys(rawData).join(', ')
: 'none (string)'}
</Text>
</Box>
);
}
}
return <Text>Unknown visualization type: {type}</Text>;
};
return (
<Box flexDirection="column" marginTop={1} marginBottom={1}>
{title && (
<Text bold color={theme.text.accent} underline>
{title}
</Text>
)}
{renderContent()}
{savedFilePath && (
<Text color={theme.status.success} dimColor>
{`Saved to: ${savedFilePath}`}
</Text>
)}
</Box>
);
};
@@ -301,4 +301,44 @@ describe('ToolResultDisplay', () => {
expect(output).not.toContain('Line 1');
expect(output).toContain('Line 50');
});
it('renders rich visualization result (diff)', () => {
const richResult = {
type: 'diff' as const,
data: {
fileDiff:
'diff --git a/test.ts b/test.ts\n--- a/test.ts\n+++ b/test.ts\n@@ -1 +1 @@\n-old\n+new',
fileName: 'test.ts',
},
};
const { lastFrame } = render(
<ToolResultDisplay
resultDisplay={richResult}
terminalWidth={80}
availableTerminalHeight={20}
/>,
);
const output = lastFrame();
expect(output).toContain('old');
expect(output).toContain('new');
});
it('renders rich visualization result (table)', () => {
const richResult = {
type: 'table' as const,
data: [{ name: 'Test', value: 123 }],
};
const { lastFrame } = render(
<ToolResultDisplay
resultDisplay={richResult}
terminalWidth={80}
availableTerminalHeight={20}
/>,
);
const output = lastFrame();
expect(output).toContain('Test');
expect(output).toContain('123');
});
});
@@ -11,7 +11,11 @@ import { MarkdownDisplay } from '../../utils/MarkdownDisplay.js';
import { AnsiOutputText, AnsiLineText } from '../AnsiOutput.js';
import { MaxSizedBox } from '../shared/MaxSizedBox.js';
import { theme } from '../../semantic-colors.js';
import type { AnsiOutput, AnsiLine } from '@google/gemini-cli-core';
import type {
AnsiOutput,
AnsiLine,
RichVisualization,
} from '@google/gemini-cli-core';
import { useUIState } from '../../contexts/UIStateContext.js';
import { tryParseJSON } from '../../../utils/jsonoutput.js';
import { useAlternateBuffer } from '../../hooks/useAlternateBuffer.js';
@@ -19,6 +23,7 @@ import { Scrollable } from '../shared/Scrollable.js';
import { ScrollableList } from '../shared/ScrollableList.js';
import { SCROLL_TO_ITEM_END } from '../shared/VirtualizedList.js';
import { ACTIVE_SHELL_MAX_LINES } from '../../constants.js';
import { RichDataDisplay } from './RichDataDisplay.js';
const STATIC_HEIGHT = 1;
const RESERVED_LINE_COUNT = 6; // for tool name, status, padding, and 'ShowMoreLines' hint
@@ -190,6 +195,20 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
terminalWidth={childWidth}
/>
);
} else if (
typeof truncatedResultDisplay === 'object' &&
'type' in truncatedResultDisplay &&
'data' in truncatedResultDisplay &&
['table', 'bar_chart', 'pie_chart', 'line_chart', 'diff'].includes(
(truncatedResultDisplay as RichVisualization).type,
)
) {
content = (
<RichDataDisplay
data={truncatedResultDisplay as RichVisualization}
availableWidth={childWidth}
/>
);
} else {
const shouldDisableTruncation =
isAlternateBuffer ||
+1
View File
@@ -55,6 +55,7 @@ const noColorSemanticColors: SemanticColors = {
error: '',
success: '',
warning: '',
info: '',
},
};
@@ -35,6 +35,7 @@ export interface SemanticColors {
error: string;
success: string;
warning: string;
info: string;
};
}
@@ -67,6 +68,7 @@ export const lightSemanticColors: SemanticColors = {
error: lightTheme.AccentRed,
success: lightTheme.AccentGreen,
warning: lightTheme.AccentYellow,
info: lightTheme.AccentBlue,
},
};
@@ -99,6 +101,7 @@ export const darkSemanticColors: SemanticColors = {
error: darkTheme.AccentRed,
success: darkTheme.AccentGreen,
warning: darkTheme.AccentYellow,
info: darkTheme.AccentBlue,
},
};
@@ -131,5 +134,6 @@ export const ansiSemanticColors: SemanticColors = {
error: ansiTheme.AccentRed,
success: ansiTheme.AccentGreen,
warning: ansiTheme.AccentYellow,
info: ansiTheme.AccentBlue,
},
};
+2
View File
@@ -149,6 +149,7 @@ export class Theme {
error: this.colors.AccentRed,
success: this.colors.AccentGreen,
warning: this.colors.AccentYellow,
info: this.colors.AccentBlue,
},
};
this._colorMap = Object.freeze(this._buildColorMap(rawMappings)); // Build and freeze the map
@@ -414,6 +415,7 @@ export function createCustomTheme(customTheme: CustomTheme): Theme {
error: customTheme.status?.error ?? colors.AccentRed,
success: customTheme.status?.success ?? colors.AccentGreen,
warning: customTheme.status?.warning ?? colors.AccentYellow,
info: customTheme.status?.info ?? colors.AccentBlue,
},
};
@@ -177,13 +177,67 @@ export const RenderInline = React.memo(RenderInlineInternal);
* This is useful for calculating column widths in tables
*/
export const getPlainTextLength = (text: string): number => {
const cleanText = text
.replace(/\*\*(.*?)\*\*/g, '$1')
.replace(/\*(.+?)\*/g, '$1')
.replace(/_(.*?)_/g, '$1')
.replace(/~~(.*?)~~/g, '$1')
.replace(/`(.*?)`/g, '$1')
.replace(/<u>(.*?)<\/u>/g, '$1')
.replace(/.*\[(.*?)\]\(.*\)/g, '$1');
const inlineRegex =
/(\*\*.*?\*\*|\*.*?\*|_.*?_|~~.*?~~|\[.*?\]\(.*?\)|`+.+?`+|<u>.*?<\/u>|https?:\/\/\S+)/g;
const cleanText = text.replace(inlineRegex, (fullMatch) => {
if (
fullMatch.startsWith('**') &&
fullMatch.endsWith('**') &&
fullMatch.length > BOLD_MARKER_LENGTH * 2
) {
return fullMatch.slice(BOLD_MARKER_LENGTH, -BOLD_MARKER_LENGTH);
}
if (
fullMatch.length > ITALIC_MARKER_LENGTH * 2 &&
((fullMatch.startsWith('*') && fullMatch.endsWith('*')) ||
(fullMatch.startsWith('_') && fullMatch.endsWith('_')))
) {
return fullMatch.slice(ITALIC_MARKER_LENGTH, -ITALIC_MARKER_LENGTH);
}
if (
fullMatch.startsWith('~~') &&
fullMatch.endsWith('~~') &&
fullMatch.length > STRIKETHROUGH_MARKER_LENGTH * 2
) {
return fullMatch.slice(
STRIKETHROUGH_MARKER_LENGTH,
-STRIKETHROUGH_MARKER_LENGTH,
);
}
if (
fullMatch.startsWith('`') &&
fullMatch.endsWith('`') &&
fullMatch.length > INLINE_CODE_MARKER_LENGTH
) {
const codeMatch = fullMatch.match(/^(`+)(.+?)\1$/s);
if (codeMatch && codeMatch[2]) {
return codeMatch[2];
}
}
if (
fullMatch.startsWith('[') &&
fullMatch.includes('](') &&
fullMatch.endsWith(')')
) {
const linkMatch = fullMatch.match(/\[(.*?)\]\((.*?)\)/);
if (linkMatch) {
return linkMatch[1];
}
}
if (
fullMatch.startsWith('<u>') &&
fullMatch.endsWith('</u>') &&
fullMatch.length >
UNDERLINE_TAG_START_LENGTH + UNDERLINE_TAG_END_LENGTH - 1
) {
return fullMatch.slice(
UNDERLINE_TAG_START_LENGTH,
-UNDERLINE_TAG_END_LENGTH,
);
}
return fullMatch;
});
return stringWidth(cleanText);
};
+3
View File
@@ -34,6 +34,7 @@ import { WebFetchTool } from '../tools/web-fetch.js';
import { MemoryTool, setGeminiMdFilename } from '../tools/memoryTool.js';
import { WebSearchTool } from '../tools/web-search.js';
import { AskUserTool } from '../tools/ask-user.js';
import { VisualizeTool } from '../tools/visualize.js';
import { ExitPlanModeTool } from '../tools/exit-plan-mode.js';
import { EnterPlanModeTool } from '../tools/enter-plan-mode.js';
import { GeminiClient } from '../core/client.js';
@@ -217,6 +218,7 @@ export interface CustomTheme {
error?: string;
success?: string;
warning?: string;
info?: string;
};
// Legacy properties (all optional)
@@ -2198,6 +2200,7 @@ export class Config {
registerCoreTool(MemoryTool);
registerCoreTool(WebSearchTool, this);
registerCoreTool(AskUserTool);
registerCoreTool(VisualizeTool, this.messageBus);
if (this.getUseWriteTodos()) {
registerCoreTool(WriteTodosTool);
}
@@ -90,6 +90,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -212,6 +213,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -293,6 +295,14 @@ Use 'read_file' to understand context and validate any assumptions you may have.
5. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.
6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell tool output token efficiency:
@@ -311,6 +321,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -428,6 +439,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -517,6 +529,14 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
5. **Verify:** Review work against the original request. Fix bugs and deviations. Ensure styling and interactions produce a high-quality, functional, and beautiful prototype. **Build the application and ensure there are no compile errors.**
6. **Solicit Feedback:** Provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell Tool Efficiency
@@ -530,6 +550,7 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
- **Concise & Direct:** Adopt a professional, direct, and concise tone suitable for a CLI environment.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes...") unless they serve to explain intent as required by the 'Explain Before Acting' mandate.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **No Repetition:** Once you have provided a final synthesis of your work, do not repeat yourself or provide additional summaries. For simple or direct requests, prioritize extreme brevity.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls.
@@ -634,6 +655,14 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
3. **Implementation:** Autonomously implement each feature per the approved plan. When starting, scaffold the application using 'run_shell_command'. For visual assets, utilize **platform-native primitives** (e.g., stylized shapes, gradients, icons). Never link to external services or assume local paths for assets that have not been created.
4. **Verify:** Review work against the original request. Fix bugs and deviations. **Build the application and ensure there are no compile errors.**
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell Tool Efficiency
@@ -647,6 +676,7 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
- **Concise & Direct:** Adopt a professional, direct, and concise tone suitable for a CLI environment.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes...") unless they serve to explain intent as required by the 'Explain Before Acting' mandate.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **No Repetition:** Once you have provided a final synthesis of your work, do not repeat yourself or provide additional summaries. For simple or direct requests, prioritize extreme brevity.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls.
@@ -734,6 +764,14 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
3. **Implementation:** Autonomously implement each feature per the approved plan. When starting, scaffold the application using 'run_shell_command'. For visual assets, utilize **platform-native primitives** (e.g., stylized shapes, gradients, icons). Never link to external services or assume local paths for assets that have not been created.
4. **Verify:** Review work against the original request. Fix bugs and deviations. **Build the application and ensure there are no compile errors.**
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell Tool Efficiency
@@ -747,6 +785,7 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
- **Concise & Direct:** Adopt a professional, direct, and concise tone suitable for a CLI environment.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes...") unless they serve to explain intent as required by the 'Explain Before Acting' mandate.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **No Repetition:** Once you have provided a final synthesis of your work, do not repeat yourself or provide additional summaries. For simple or direct requests, prioritize extreme brevity.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls.
@@ -827,6 +866,14 @@ Use 'read_file' to understand context and validate any assumptions you may have.
5. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.
6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell tool output token efficiency:
@@ -845,6 +892,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -926,6 +974,14 @@ Use 'read_file' to understand context and validate any assumptions you may have.
5. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.
6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell tool output token efficiency:
@@ -944,6 +1000,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -1033,6 +1090,14 @@ Use 'read_file' to understand context and validate any assumptions you may have.
3. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.
4. **Finish:** Provide a brief summary of what was built.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell tool output token efficiency:
@@ -1051,6 +1116,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -1145,6 +1211,14 @@ Use 'read_file' to understand context and validate any assumptions you may have.
5. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.
6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell tool output token efficiency:
@@ -1163,6 +1237,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -1244,6 +1319,14 @@ Use 'read_file' to understand context and validate any assumptions you may have.
5. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.
6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell tool output token efficiency:
@@ -1262,6 +1345,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -1343,6 +1427,14 @@ Use 'read_file' to understand context and validate any assumptions you may have.
5. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.
6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell tool output token efficiency:
@@ -1361,6 +1453,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -1442,6 +1535,14 @@ Use 'read_file' to understand context and validate any assumptions you may have.
5. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.
6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell tool output token efficiency:
@@ -1460,6 +1561,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -1541,6 +1643,14 @@ Use 'read_file' to understand context and validate any assumptions you may have.
5. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.
6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell tool output token efficiency:
@@ -1559,6 +1669,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -1640,6 +1751,14 @@ Use 'read_file' to understand context and validate any assumptions you may have.
5. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.
6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell tool output token efficiency:
@@ -1658,6 +1777,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -1747,6 +1867,14 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
5. **Verify:** Review work against the original request. Fix bugs and deviations. Ensure styling and interactions produce a high-quality, functional, and beautiful prototype. **Build the application and ensure there are no compile errors.**
6. **Solicit Feedback:** Provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell Tool Efficiency
@@ -1760,6 +1888,7 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
- **Concise & Direct:** Adopt a professional, direct, and concise tone suitable for a CLI environment.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes...") unless they serve to explain intent as required by the 'Explain Before Acting' mandate.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **No Repetition:** Once you have provided a final synthesis of your work, do not repeat yourself or provide additional summaries. For simple or direct requests, prioritize extreme brevity.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls.
@@ -1848,6 +1977,14 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
5. **Verify:** Review work against the original request. Fix bugs and deviations. Ensure styling and interactions produce a high-quality, functional, and beautiful prototype. **Build the application and ensure there are no compile errors.**
6. **Solicit Feedback:** Provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell Tool Efficiency
@@ -1861,6 +1998,7 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
- **Concise & Direct:** Adopt a professional, direct, and concise tone suitable for a CLI environment.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes...") unless they serve to explain intent as required by the 'Explain Before Acting' mandate.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **No Repetition:** Once you have provided a final synthesis of your work, do not repeat yourself or provide additional summaries. For simple or direct requests, prioritize extreme brevity.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls.
@@ -1940,6 +2078,14 @@ Use 'read_file' to understand context and validate any assumptions you may have.
3. **Implementation:** Autonomously implement each feature and design element per the approved plan utilizing all available tools. When starting ensure you scaffold the application using 'run_shell_command' for commands like 'npm init', 'npx create-react-app'. Aim for full scope completion. Proactively create or source necessary placeholder assets (e.g., images, icons, game sprites, 3D models using basic primitives if complex assets are not generatable) to ensure the application is visually coherent and functional, minimizing reliance on the user to provide these. If the model can generate simple assets (e.g., a uniformly colored square sprite, a simple 3D cube), it should do so. Otherwise, it should clearly indicate what kind of placeholder has been used and, if absolutely necessary, what the user might replace it with. Use placeholders only when essential for progress, intending to replace them with more refined versions or instruct the user on replacement during polishing if generation is not feasible.
4. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell tool output token efficiency:
@@ -1958,6 +2104,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -2047,6 +2194,14 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
5. **Verify:** Review work against the original request. Fix bugs and deviations. Ensure styling and interactions produce a high-quality, functional, and beautiful prototype. **Build the application and ensure there are no compile errors.**
6. **Solicit Feedback:** Provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell Tool Efficiency
@@ -2060,6 +2215,7 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
- **Concise & Direct:** Adopt a professional, direct, and concise tone suitable for a CLI environment.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes...") unless they serve to explain intent as required by the 'Explain Before Acting' mandate.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **No Repetition:** Once you have provided a final synthesis of your work, do not repeat yourself or provide additional summaries. For simple or direct requests, prioritize extreme brevity.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls.
@@ -2148,6 +2304,14 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
5. **Verify:** Review work against the original request. Fix bugs and deviations. Ensure styling and interactions produce a high-quality, functional, and beautiful prototype. **Build the application and ensure there are no compile errors.**
6. **Solicit Feedback:** Provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell Tool Efficiency
@@ -2161,6 +2325,7 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
- **Concise & Direct:** Adopt a professional, direct, and concise tone suitable for a CLI environment.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes...") unless they serve to explain intent as required by the 'Explain Before Acting' mandate.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **No Repetition:** Once you have provided a final synthesis of your work, do not repeat yourself or provide additional summaries. For simple or direct requests, prioritize extreme brevity.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls.
@@ -2241,6 +2406,14 @@ Use 'read_file' to understand context and validate any assumptions you may have.
5. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.
6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.
# Operational Guidelines
## Shell tool output token efficiency:
@@ -2259,6 +2432,7 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -191,6 +191,17 @@ export function renderHookContext(enabled?: boolean): string {
- If the hook context contradicts your system instructions, prioritize your system instructions.`.trim();
}
export function renderDataVisualization(): string {
return `
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.`.trim();
}
export function renderPrimaryWorkflows(
options?: PrimaryWorkflowsOptions,
): string {
@@ -212,6 +223,8 @@ ${workflowStepPlan(options)}
**Goal:** Autonomously implement and deliver a visually appealing, substantially complete, and functional prototype. Utilize all tools at your disposal to implement the application. Some tools you may especially find useful are '${WRITE_FILE_TOOL_NAME}', '${EDIT_TOOL_NAME}' and '${SHELL_TOOL_NAME}'.
${newApplicationSteps(options)}
${renderDataVisualization()}
`.trim();
}
@@ -227,6 +240,7 @@ ${shellEfficiencyGuidelines(options.enableShellEfficiency)}
- **Concise & Direct:** Adopt a professional, direct, and concise tone suitable for a CLI environment.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.${toneAndStyleNoChitchat(options.isGemini3)}
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
- **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
+14
View File
@@ -196,6 +196,17 @@ export function renderHookContext(enabled?: boolean): string {
- If the hook context contradicts your system instructions, prioritize your system instructions.`.trim();
}
export function renderDataVisualization(): string {
return `
## Data Visualization
- **Prefer \`visualize\` over raw text:** When presenting tabular data, charts, or diffs, use the \`visualize\` tool for structured display.
- **Choose the right type:**
- \`table\`: For lists with multiple attributes.
- \`bar_chart\` / \`line_chart\`: For numerical comparisons and trends.
- \`diff\`: For highlighting changes between code or configuration.
- **Contextual Clarity:** Provide a descriptive \`title\` and ensure \`data\` is correctly formatted. For \`diff\`, \`data\` should be a unified diff string or an object with \`oldContent\` and \`newContent\`.`.trim();
}
export function renderPrimaryWorkflows(
options?: PrimaryWorkflowsOptions,
): string {
@@ -220,6 +231,8 @@ ${workflowStepStrategy(options)}
**Goal:** Autonomously implement and deliver a visually appealing, substantially complete, and functional prototype with rich aesthetics. Users judge applications by their visual impact; ensure they feel modern, "alive," and polished through consistent spacing, interactive feedback, and platform-appropriate design.
${newApplicationSteps(options)}
${renderDataVisualization()}
`.trim();
}
@@ -236,6 +249,7 @@ ${shellEfficiencyGuidelines(options.enableShellEfficiency)}
- **High-Signal Output:** Focus exclusively on **intent** and **technical rationale**. Avoid conversational filler, apologies, and mechanical tool-use narration (e.g., "I will now call...").
- **Concise & Direct:** Adopt a professional, direct, and concise tone suitable for a CLI environment.
- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical.${toneAndStyleNoChitchat(options.isGemini3)}
- **Structured Outputs:** Prioritize structured visualizations using the visualize tool for complex data (such as tables, comparisons, or trends) over manual markdown formatting or long, unformatted lists.
- **No Repetition:** Once you have provided a final synthesis of your work, do not repeat yourself or provide additional summaries. For simple or direct requests, prioritize extreme brevity.
- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
- **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls.
+14 -1
View File
@@ -648,7 +648,20 @@ export interface TodoList {
todos: Todo[];
}
export type ToolResultDisplay = string | FileDiff | AnsiOutput | TodoList;
export interface RichVisualization {
type: 'table' | 'bar_chart' | 'pie_chart' | 'line_chart' | 'diff';
title?: string;
data: unknown;
columns?: Array<{ key: string; label: string }>;
savedFilePath?: string;
}
export type ToolResultDisplay =
| string
| FileDiff
| AnsiOutput
| TodoList
| RichVisualization;
export type TodoStatus = 'pending' | 'in_progress' | 'completed' | 'cancelled';
+107
View File
@@ -0,0 +1,107 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { VisualizeTool } from './visualize.js';
import type { MessageBus } from '../confirmation-bus/message-bus.js';
import * as fs from 'node:fs/promises';
vi.mock('node:fs/promises');
vi.mock('../confirmation-bus/message-bus.js');
describe('VisualizeTool', () => {
let tool: VisualizeTool;
let messageBus: MessageBus;
beforeEach(() => {
messageBus = {} as unknown as MessageBus;
tool = new VisualizeTool(messageBus);
});
it('should return table visualization', async () => {
const data = [{ name: 'A', value: 1 }];
const result = await tool.validateBuildAndExecute(
{ data, type: 'table' },
new AbortController().signal,
);
expect(result.returnDisplay).toEqual({
type: 'table',
title: undefined,
data,
columns: [
{ key: 'name', label: 'name' },
{ key: 'value', label: 'value' },
],
savedFilePath: undefined,
});
});
it('should return bar_chart visualization', async () => {
const data = [{ label: 'A', value: 10 }];
const result = await tool.validateBuildAndExecute(
{ data, type: 'bar_chart' },
new AbortController().signal,
);
expect(result.returnDisplay).toMatchObject({
type: 'bar_chart',
data,
});
});
it('should save to file if save_as provided', async () => {
const data = [{ name: 'A', value: 1 }];
const savePath = '/tmp/test.json';
(fs.writeFile as unknown as ReturnType<typeof vi.fn>).mockResolvedValue(
undefined,
);
const result = await tool.validateBuildAndExecute(
{ data, save_as: savePath },
new AbortController().signal,
);
expect(fs.writeFile).toHaveBeenCalledWith(
expect.stringContaining('test.json'),
expect.stringContaining('"name": "A"'),
);
expect(
(result.returnDisplay as { savedFilePath: string }).savedFilePath,
).toBeTruthy();
});
it('should return error if data is not an array', async () => {
const result = await tool.validateBuildAndExecute(
{ data: 'invalid' as unknown as Array<Record<string, unknown>> },
new AbortController().signal,
);
expect(result.error).toBeDefined();
expect(result.error?.message).toContain('Data must be an array');
});
it('should return diff visualization', async () => {
const data = { fileDiff: 'diff...', fileName: 'test.ts' };
const result = await tool.validateBuildAndExecute(
{ data, type: 'diff' },
new AbortController().signal,
);
expect(result.returnDisplay).toMatchObject({
type: 'diff',
data,
});
});
it('should return line_chart visualization', async () => {
const data = [{ label: 'Jan', value: 100 }];
const result = await tool.validateBuildAndExecute(
{ data, type: 'line_chart' },
new AbortController().signal,
);
expect(result.returnDisplay).toMatchObject({
type: 'line_chart',
data,
});
});
});
+204
View File
@@ -0,0 +1,204 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { BaseDeclarativeTool, BaseToolInvocation, Kind } from './tools.js';
import type { ToolInvocation, ToolResult } from './tools.js';
import type { MessageBus } from '../confirmation-bus/message-bus.js';
import * as fs from 'node:fs/promises';
import * as path from 'node:path';
import { ToolErrorType } from './tool-error.js';
interface VisualizeParams {
data: unknown;
type?: 'table' | 'bar_chart' | 'pie_chart' | 'line_chart' | 'diff';
title?: string;
save_as?: string;
open?: boolean;
}
class VisualizeInvocation extends BaseToolInvocation<
VisualizeParams,
ToolResult
> {
getDescription(): string {
const type = this.params.type ?? 'table';
const action = this.params.save_as
? `and saving to ${this.params.save_as}`
: '';
return `Visualizing data as ${type} ${action}`;
}
async execute(
_signal: AbortSignal,
_updateOutput?: (output: string) => void,
): Promise<ToolResult> {
const { data, type = 'table', title, save_as } = this.params;
if (
type === 'table' ||
type === 'bar_chart' ||
type === 'pie_chart' ||
type === 'line_chart'
) {
if (!Array.isArray(data)) {
return {
llmContent:
'Error: data must be an array of objects for this visualization type.',
returnDisplay:
'Error: data must be an array of objects for this visualization type.',
error: {
message: 'Data must be an array',
type: ToolErrorType.INVALID_TOOL_PARAMS,
},
};
}
} else if (type === 'diff') {
if (typeof data !== 'object' || !data) {
return {
llmContent: 'Error: data must be an object for diff visualization.',
returnDisplay:
'Error: data must be an object for diff visualization.',
error: {
message: 'Data must be an object',
type: ToolErrorType.INVALID_TOOL_PARAMS,
},
};
}
}
let savedFilePath: string | undefined;
if (save_as) {
try {
const absolutePath = path.resolve(save_as);
let content = '';
if (save_as.endsWith('.json')) {
content = JSON.stringify(data, null, 2);
} else if (save_as.endsWith('.csv') && Array.isArray(data)) {
// Basic CSV conversion
if (data.length > 0 && typeof data[0] === 'object') {
const headers = Object.keys(data[0] as object).join(',');
const rows = data
.map((row) =>
Object.values(row as object)
.map((v) => {
const s = String(v);
// Quote if contains comma or newline
if (
s.includes(',') ||
s.includes('\n') ||
s.includes('"')
) {
return `"${s.replace(/"/g, '""')}"`;
}
return s;
})
.join(','),
)
.join('\n');
content = `${headers}\n${rows}`;
} else {
content = '';
}
} else {
content = JSON.stringify(data, null, 2);
}
await fs.writeFile(absolutePath, content);
savedFilePath = absolutePath;
} catch (e) {
return {
llmContent: `Error saving file: ${e}`,
returnDisplay: `Error saving file: ${e}`,
error: {
message: `Error saving file: ${e}`,
type: ToolErrorType.EXECUTION_FAILED,
},
};
}
}
// Infer columns for table
let columns;
if (
type === 'table' &&
Array.isArray(data) &&
data.length > 0 &&
typeof data[0] === 'object'
) {
columns = Object.keys(data[0] as object).map((key) => ({
key,
label: key,
}));
}
return {
llmContent:
'Visualization rendered in CLI.' +
(savedFilePath ? ` Saved to ${savedFilePath}` : ''),
returnDisplay: {
type,
title,
data,
columns,
savedFilePath,
},
};
}
}
export class VisualizeTool extends BaseDeclarativeTool<
VisualizeParams,
ToolResult
> {
constructor(messageBus: MessageBus) {
super(
'visualize',
'Visualize Data',
'Renders structured data as tables, charts, or diffs, and optionally saves it to a file.',
Kind.Other,
{
type: 'object',
properties: {
data: {
description:
'The structured data to visualize. Array of objects for tables/charts. For diffs, provide an object with {fileDiff: string}, {old: string, new: string}, or {oldContent: string, newContent: string}. Can also be a string containing a unified diff.',
},
type: {
type: 'string',
enum: ['table', 'bar_chart', 'pie_chart', 'line_chart', 'diff'],
description: 'The visualization type. Default: table.',
},
title: {
type: 'string',
description: 'A title for the visualization.',
},
save_as: {
type: 'string',
description:
'File path to save the data (e.g. data.csv, data.json).',
},
},
required: ['data'],
},
messageBus,
);
}
protected createInvocation(
params: VisualizeParams,
messageBus: MessageBus,
toolName?: string,
toolDisplayName?: string,
): ToolInvocation<VisualizeParams, ToolResult> {
return new VisualizeInvocation(
params,
messageBus,
toolName ?? this.name,
toolDisplayName ?? this.displayName,
);
}
}
+13 -10
View File
@@ -18,12 +18,14 @@ import {
getCommandRoots,
getShellConfiguration,
initializeShellParsers,
resetShellParsersForTesting,
parseCommandDetails,
stripShellWrapper,
hasRedirection,
resolveExecutable,
} from './shell-utils.js';
import path from 'node:path';
import * as fileUtils from './fileUtils.js';
const mockPlatform = vi.hoisted(() => vi.fn());
const mockHomedir = vi.hoisted(() => vi.fn());
@@ -184,23 +186,24 @@ describe('getCommandRoots', () => {
});
it('should handle parser initialization failures gracefully', async () => {
// Reset modules to clear singleton state
vi.resetModules();
// Reset singleton state
resetShellParsersForTesting();
// Mock fileUtils to fail Wasm loading
vi.doMock('./fileUtils.js', () => ({
loadWasmBinary: vi.fn().mockRejectedValue(new Error('Wasm load failed')),
}));
// Re-import shell-utils with mocked dependencies
const shellUtils = await import('./shell-utils.js');
const spy = vi
.spyOn(fileUtils, 'loadWasmBinary')
.mockRejectedValue(new Error('Wasm load failed'));
// Should catch the error and not throw
await expect(shellUtils.initializeShellParsers()).resolves.not.toThrow();
await expect(initializeShellParsers()).resolves.not.toThrow();
// Fallback: splitting commands depends on parser, so if parser fails, it returns empty
const roots = shellUtils.getCommandRoots('ls -la');
const roots = getCommandRoots('ls -la');
expect(roots).toEqual([]);
spy.mockRestore();
resetShellParsersForTesting();
await initializeShellParsers();
});
it('should handle bash parser timeouts', () => {
+10
View File
@@ -139,6 +139,16 @@ export async function initializeShellParsers(): Promise<void> {
await treeSitterInitialization;
}
/**
* Resets the shell parser initialization state.
* Only for testing purposes.
*/
export function resetShellParsersForTesting(): void {
bashLanguage = null;
treeSitterInitialization = null;
treeSitterInitializationError = null;
}
export interface ParsedCommandDetail {
name: string;
text: string;