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>
105 lines
4.3 KiB
TypeScript
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
|
|
}
|
|
},
|
|
}),
|
|
})
|