/** * 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 } }, }), })