Files
Momento/memento-note/lib/ai/tools/chart-suggestion.tool.ts
Antigravity a122a0eade feat(ai): add AI chart suggestions in TipTap editor
Implement slash command "/suggest-charts" that analyzes note content
and suggests 3 appropriate chart types with visual previews.

Created:
- chart-suggestion.tool.ts: AI tool for data extraction and chart recommendations
- suggest-charts/route.ts: API endpoint for chart suggestions
- chart-suggestion.service.ts: Frontend service layer
- chart-suggestions-dialog.tsx: Modal with 3 chart proposals and thumbnails
- tiptap-chart-extension.tsx: TipTap Node extension for rendering chart blocks

Modified:
- rich-text-editor.tsx: Added slash command, toolbar button, and dialog integration

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 08:58:46 +00:00

105 lines
4.3 KiB
TypeScript

/**
* Chart Suggestion Tool for Notes
* AI analyzes note content and suggests appropriate chart types with data
*/
import { tool } from 'ai'
import { z } from 'zod'
import { toolRegistry } from './registry'
// Chart suggestion data structures
export interface ChartSuggestion {
type: 'bar' | 'horizontal-bar' | 'line' | 'area' | 'pie' | 'radar' | 'funnel' | 'gauge'
title: string
data: { label: string; value: number }[]
description: string
rationale?: string
}
export interface SuggestChartsResponse {
suggestions: ChartSuggestion[]
analyzedText: string
detectedData: string
hasData: boolean
}
toolRegistry.register({
name: 'suggest_charts',
description: 'Analyze content and suggest appropriate chart types with extracted data',
isInternal: true,
buildTool: (ctx) =>
tool({
description: `Analyze the provided text content and suggest 3 appropriate chart types with extracted data.
Available chart types:
- "bar": Vertical bar chart (best for comparing values across categories)
- "horizontal-bar": Horizontal bar chart (best for long category labels)
- "line": Line chart (best for trends over time or sequences)
- "area": Area chart (filled line chart, best for showing magnitude over time)
- "pie": Pie chart (best for showing proportions/percentages of a whole)
- "radar": Radar chart (best for comparing multiple dimensions)
- "funnel": Funnel chart (best for showing stages in a process)
- "gauge": Gauge chart (best for single values vs a target)
CRITICAL RULES:
1. Extract ONLY numerical data present in the text - do NOT invent or fabricate values
2. If fewer than 2 data points exist, return empty suggestions array with hasData=false
3. Each suggestion MUST use the SAME extracted data - only the chart type differs
4. Provide a clear rationale explaining WHY each chart type suits the data
5. Generate meaningful labels - if the text provides context (months, categories, names), use those; otherwise use generic labels like "Item 1", "Item 2", etc.
Data extraction examples:
- "Sales: Jan $5000, Feb $7500, Mar $6200" → [{label:"Jan",value:5000}, {label:"Feb",value:7500}, {label:"Mar",value:6200}]
- "Product A: 45%, Product B: 30%, Product C: 25%" → [{label:"Product A",value:45}, {label:"Product B",value:30}, {label:"Product C",value:25}]
- "Progress: Q1=10, Q2=25, Q3=40, Q4=60" → [{label:"Q1",value:10}, {label:"Q2",value:25}, {label:"Q3",value:40}, {label:"Q4",value:60}]
Output format:
Return exactly 3 chart suggestions with different types. Order by relevance (most suitable first).
Example response for sales data:
{
"suggestions": [
{
"type": "bar",
"title": "Sales by Month",
"data": [{"label":"Jan","value":5000},{"label":"Feb","value":7500},{"label":"Mar","value":6200}],
"description": "Bar chart comparing sales across months",
"rationale": "Best for direct comparison of values between categories"
},
{
"type": "line",
"title": "Sales Trend",
"data": [{"label":"Jan","value":5000},{"label":"Feb","value":7500},{"label":"Mar","value":6200}],
"description": "Line chart showing sales progression over time",
"rationale": "Ideal for visualizing trends and changes over time periods"
},
{
"type": "area",
"title": "Sales Volume",
"data": [{"label":"Jan","value":5000},{"label":"Feb","value":7500},{"label":"Mar","value":6200}],
"description": "Area chart emphasizing sales magnitude",
"rationale": "Similar to line but emphasizes volume/proportion visually"
}
],
"analyzedText": "Sales: Jan $5000, Feb $7500, Mar $6200",
"detectedData": "3 data points: sales figures for Jan, Feb, Mar",
"hasData": true
}`,
inputSchema: z.object({
content: z.string().describe('The full note content to analyze for chart data'),
selection: z.string().optional().describe('Optional selected text - if provided, analyze only this instead of full content'),
}),
execute: async ({ content, selection }) => {
const textToAnalyze = selection && selection.trim() ? selection.trim() : content.trim()
// This will be processed by the AI model
// The AI will extract data and generate suggestions
return {
textToAnalyze,
// The actual suggestion generation happens in the AI response
// This tool provides the context for the AI to work with
}
},
}),
})