mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-15 16:41:11 -07:00
246 lines
7.7 KiB
Markdown
246 lines
7.7 KiB
Markdown
|
|
# Built-in Native Visualization Tool for Gemini CLI (V1)
|
||
|
|
|
||
|
|
## Summary
|
||
|
|
|
||
|
|
Implement a first-class built-in tool `render_visualization` (no MCP) that
|
||
|
|
supports `bar`, `line`, and `table` outputs in the terminal using Ink-native
|
||
|
|
rendering. The model will be guided to use this tool during natural-language
|
||
|
|
reasoning loops (research -> normalize -> visualize), so users do not need to
|
||
|
|
format input data manually.
|
||
|
|
|
||
|
|
This design directly supports these scenarios:
|
||
|
|
|
||
|
|
- "Fastest 3 BMW + comparative 0-60 chart"
|
||
|
|
- Follow-up in same session: "BMW models per year for last 5 years" with dynamic
|
||
|
|
data volumes and consistent cross-platform rendering.
|
||
|
|
|
||
|
|
## Goals and Success Criteria
|
||
|
|
|
||
|
|
- User asks a natural-language question requiring comparison/trend display.
|
||
|
|
- Model can:
|
||
|
|
|
||
|
|
1. Gather data via existing tools (web/file/etc),
|
||
|
|
2. Transform raw findings into visualization schema,
|
||
|
|
3. Call `render_visualization` correctly,
|
||
|
|
4. Render readable inline chart/table in CLI.
|
||
|
|
|
||
|
|
- Works across modern terminals on macOS, Linux, Windows.
|
||
|
|
- Follow-up turns in same session continue to use tool correctly without user
|
||
|
|
schema knowledge.
|
||
|
|
|
||
|
|
## Product Decisions (Locked)
|
||
|
|
|
||
|
|
- V1 scope: one tool with 3 visualization types: `bar | line | table`.
|
||
|
|
- UI surface: inline tool result panel only.
|
||
|
|
- Rendering stack: pure Ink + custom renderers (no chart library dependency in
|
||
|
|
v1).
|
||
|
|
- Invocation behavior: explicit user visualization intent
|
||
|
|
(chart/show/compare/trend/table).
|
||
|
|
- Prompting: tool description + explicit system-prompt guidance snippet for
|
||
|
|
visualization decisioning.
|
||
|
|
- Data entry: primary structured schema; optional text parsing fallback for
|
||
|
|
convenience.
|
||
|
|
|
||
|
|
## Public API / Interface Changes
|
||
|
|
|
||
|
|
### New built-in tool
|
||
|
|
|
||
|
|
- Name: `render_visualization`
|
||
|
|
- Display: `Render Visualization`
|
||
|
|
- Category: built-in core tool (`Kind.Other`)
|
||
|
|
|
||
|
|
### Tool input schema
|
||
|
|
|
||
|
|
- `chartType` (required): `"bar" | "line" | "table"`
|
||
|
|
- `title` (optional): string
|
||
|
|
- `subtitle` (optional): string
|
||
|
|
- `xLabel` (optional): string
|
||
|
|
- `yLabel` (optional): string
|
||
|
|
- `series` (required): array of series
|
||
|
|
- `series[].name` (required): string
|
||
|
|
- `series[].points` (required): array of `{ label: string, value: number }`
|
||
|
|
- `sort` (optional): `"none" | "asc" | "desc"` (applies to single-series
|
||
|
|
bar/table)
|
||
|
|
- `maxPoints` (optional): number (default 30, cap 200)
|
||
|
|
- `inputText` (optional fallback): string (JSON/table/CSV-like text to parse
|
||
|
|
when `series` omitted)
|
||
|
|
- `unit` (optional): string (e.g., `"s"`)
|
||
|
|
|
||
|
|
### Tool output display type
|
||
|
|
|
||
|
|
Add new `ToolResultDisplay` variant:
|
||
|
|
|
||
|
|
- `VisualizationDisplay`:
|
||
|
|
- `type: "visualization"`
|
||
|
|
- `chartType: "bar" | "line" | "table"`
|
||
|
|
- `title?`, `subtitle?`, `xLabel?`, `yLabel?`, `unit?`
|
||
|
|
- `series`
|
||
|
|
- `meta`:
|
||
|
|
`{ truncated: boolean, originalPointCount: number, fallbackMode?: "unicode"|"ascii" }`
|
||
|
|
|
||
|
|
## Architecture and Data Flow
|
||
|
|
|
||
|
|
## 1. Tool implementation (core)
|
||
|
|
|
||
|
|
- New file: `packages/core/src/tools/render-visualization.ts`
|
||
|
|
- Implements validation + normalization pipeline:
|
||
|
|
|
||
|
|
1. Resolve input source:
|
||
|
|
|
||
|
|
- use `series` if provided,
|
||
|
|
- else parse `inputText`.
|
||
|
|
|
||
|
|
2. Validate numeric values (finite only), normalize labels as strings.
|
||
|
|
3. Apply chart-specific constraints:
|
||
|
|
|
||
|
|
- `line`: preserve chronological order unless explicit sort disabled.
|
||
|
|
- `bar/table`: optional sort.
|
||
|
|
|
||
|
|
4. Apply volume controls (`maxPoints`, truncation metadata).
|
||
|
|
5. Return:
|
||
|
|
|
||
|
|
- `llmContent`: concise factual summary + normalized data preview.
|
||
|
|
- `returnDisplay`: typed `VisualizationDisplay`.
|
||
|
|
|
||
|
|
## 2. Built-in registration
|
||
|
|
|
||
|
|
- Register in `packages/core/src/config/config.ts` (`createToolRegistry()`).
|
||
|
|
- Add tool-name constants and built-in lists:
|
||
|
|
- `packages/core/src/tools/tool-names.ts`
|
||
|
|
- `packages/core/src/tools/definitions/coreTools.ts`
|
||
|
|
|
||
|
|
## 3. Prompt guidance (critical for this scenario)
|
||
|
|
|
||
|
|
- Update prompt snippets so model reliably chooses this tool:
|
||
|
|
- In tool-usage guidance section: "When user asks to compare, chart, trend, or
|
||
|
|
show tabular metrics, gather/compute data first, then call
|
||
|
|
`render_visualization` with structured series."
|
||
|
|
- Keep short and deterministic; do not over-prescribe style.
|
||
|
|
- Include 1 canonical example in tool description: "BMW 0-60 comparison."
|
||
|
|
|
||
|
|
## 4. CLI rendering (Ink)
|
||
|
|
|
||
|
|
- Extend `packages/cli/src/ui/components/messages/ToolResultDisplay.tsx` to
|
||
|
|
handle `VisualizationDisplay`.
|
||
|
|
- Add renderer components:
|
||
|
|
- `VisualizationDisplay.tsx` dispatcher
|
||
|
|
- `BarChartDisplay.tsx`
|
||
|
|
- `LineChartDisplay.tsx`
|
||
|
|
- `TableVizDisplay.tsx`
|
||
|
|
|
||
|
|
### Rendering behavior
|
||
|
|
|
||
|
|
- Inline panel, width-aware, no alternate screen required.
|
||
|
|
- Unicode first (`█`, box chars), ASCII fallback when needed.
|
||
|
|
- Label truncation + right-aligned values.
|
||
|
|
- Height caps to preserve conversational viewport.
|
||
|
|
- Multi-series behavior:
|
||
|
|
- V1: `line` supports multi-series.
|
||
|
|
- `bar/table`: single-series required in v1 (validation error if more than one).
|
||
|
|
|
||
|
|
## 5. Natural-language to schema reliability strategy
|
||
|
|
|
||
|
|
- Primary expectation: model transforms researched data into `series`.
|
||
|
|
- Fallback parser for `inputText` supports:
|
||
|
|
- JSON object map
|
||
|
|
- JSON array records
|
||
|
|
- Markdown table
|
||
|
|
- CSV-like 2-column text
|
||
|
|
- Ambiguous prose parsing intentionally rejected with actionable error +
|
||
|
|
accepted examples.
|
||
|
|
- This avoids silent bad charts and improves reasoning-loop consistency.
|
||
|
|
|
||
|
|
## 6. Dynamic volume strategy
|
||
|
|
|
||
|
|
- Defaults:
|
||
|
|
- `maxPoints = 30`
|
||
|
|
- Hard cap `200`
|
||
|
|
- For larger sets:
|
||
|
|
- `bar/table`: keep top N by absolute value (or chronological when user asks
|
||
|
|
"last N years").
|
||
|
|
- `line`: downsample uniformly while preserving first/last points.
|
||
|
|
- Always annotate truncation in `meta` and human-readable footer.
|
||
|
|
|
||
|
|
## Testing Plan
|
||
|
|
|
||
|
|
## Core tests
|
||
|
|
|
||
|
|
- New: `packages/core/src/tools/render-visualization.test.ts`
|
||
|
|
- Cases:
|
||
|
|
- Valid single-series bar (BMW 0-60 style).
|
||
|
|
- Valid line trend (yearly counts).
|
||
|
|
- Valid table rendering payload.
|
||
|
|
- Multi-series line accepted.
|
||
|
|
- Multi-series bar rejected.
|
||
|
|
- `inputText` parse success for JSON/table/CSV.
|
||
|
|
- Ambiguous prose rejected with guidance.
|
||
|
|
- Sort behavior correctness.
|
||
|
|
- Volume truncation/downsampling correctness.
|
||
|
|
- Unit handling and numeric validation.
|
||
|
|
|
||
|
|
## Registration and schema tests
|
||
|
|
|
||
|
|
- Update `packages/core/src/config/config.test.ts`:
|
||
|
|
- tool registers by default
|
||
|
|
- respects `tools.core` allowlist and `tools.exclude`
|
||
|
|
- Update tool definition snapshots for model function declarations.
|
||
|
|
|
||
|
|
## Prompt tests
|
||
|
|
|
||
|
|
- Update prompt snapshot tests to assert presence of visualization guidance line
|
||
|
|
and tool name substitution.
|
||
|
|
|
||
|
|
## UI tests
|
||
|
|
|
||
|
|
- New:
|
||
|
|
- `packages/cli/src/ui/components/messages/VisualizationDisplay.test.tsx`
|
||
|
|
- `BarChartDisplay.test.tsx`
|
||
|
|
- `LineChartDisplay.test.tsx`
|
||
|
|
- `TableVizDisplay.test.tsx`
|
||
|
|
- Validate:
|
||
|
|
- width adaptation (narrow/normal)
|
||
|
|
- unicode/ascii fallback
|
||
|
|
- long labels
|
||
|
|
- truncation indicators
|
||
|
|
- no overflow crashes
|
||
|
|
|
||
|
|
## Integration tests
|
||
|
|
|
||
|
|
- Add scenario tests for:
|
||
|
|
|
||
|
|
1. Research + bar chart call pattern.
|
||
|
|
2. Same-session follow-up question with different metric and chart type.
|
||
|
|
|
||
|
|
- Validate tool call args shape and final rendered output branch selection.
|
||
|
|
|
||
|
|
## Rollout Plan
|
||
|
|
|
||
|
|
- Feature flag: `experimental.visualizationToolV1` default `false`.
|
||
|
|
- Dogfood + internal beta.
|
||
|
|
- Telemetry:
|
||
|
|
- invocation rate
|
||
|
|
- schema validation failure rate
|
||
|
|
- parse fallback usage
|
||
|
|
- render fallback (unicode->ascii) rate
|
||
|
|
- per-chart-type success.
|
||
|
|
- Flip default to `true` after stability threshold.
|
||
|
|
|
||
|
|
## Risks and Mitigations
|
||
|
|
|
||
|
|
- Risk: model under-calls tool.
|
||
|
|
- Mitigation: explicit prompt guidance + strong tool description examples.
|
||
|
|
- Risk: terminal incompatibilities.
|
||
|
|
- Mitigation: deterministic ASCII fallback and conservative layout.
|
||
|
|
- Risk: oversized datasets.
|
||
|
|
- Mitigation: hard caps + truncation/downsampling metadata.
|
||
|
|
- Risk: noisy prose parsing.
|
||
|
|
- Mitigation: strict parser and explicit rejection path.
|
||
|
|
|
||
|
|
## Assumptions and Defaults
|
||
|
|
|
||
|
|
- Modern terminal baseline supports ANSI color and common Unicode; fallback
|
||
|
|
always available.
|
||
|
|
- V1 interactivity (keyboard-driven selections/buttons) is out of scope.
|
||
|
|
- Browser/WebView rendering is out of scope.
|
||
|
|
- V1 excludes negative-value bars.
|