fix(chart): improve error handling and color variety

- Add quotaExceeded flag to response for better error UX
- Show dedicated quota exceeded state with upgrade button
- Improve AI prompt to better detect data patterns
- Add chart type-specific colors (blue, indigo, emerald, violet, etc.)
- Replace generic primary/10 colors with varied accent colors

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Antigravity
2026-05-23 09:19:52 +00:00
parent a122a0eade
commit 18ffd76c1e
16 changed files with 1042 additions and 134 deletions

View File

@@ -8,14 +8,14 @@ import { z } from 'zod'
import { toolRegistry } from './registry'
import { prisma } from '@/lib/prisma'
// Simple chart insertion tool - does everything in one call
// Simple chart generation tool - returns markdown chart
toolRegistry.register({
name: 'insert_chart',
description: 'Generate a chart and insert it directly into a note. Use when the user asks for a chart, graph, or visualization.',
description: 'Generate a chart and return it as markdown. Use when the user asks for a chart, graph, or visualization.',
isInternal: true,
buildTool: (ctx) =>
tool({
description: `Generate a chart and insert it directly into the note content.
description: `Generate a chart as markdown that will be rendered as an interactive chart.
Available chart types:
- "bar": Vertical bar chart (default for comparisons)
@@ -25,11 +25,9 @@ Available chart types:
- "pie": Pie chart (use for proportions/percentages)
- "radar": Radar chart (use for comparing multiple dimensions)
IMPORTANT: When the user asks for a chart/graph/visualization:
1. Extract the data from the note or user request
2. Choose the appropriate chart type based on the data
3. Generate the chart markdown using this format:
CRITICAL - NEVER use Mermaid, flowchart, or other markdown diagram formats. ALWAYS use this tool to generate charts.
Chart format:
\`\`\`chart
{chartType}
{title}
@@ -47,38 +45,22 @@ Feb: 7500
Mar: 6200
\`\`\`
4. Call this tool with the noteId, the chart markdown, and where to insert it`,
Example for "show MRR progression":
\`\`\`chart
line
MRR Growth
Month 1: 2000
Month 2: 4500
Month 3: 8900
\`\`\``,
inputSchema: z.object({
noteId: z.string().describe('The note ID to update'),
chartMarkdown: z.string().describe('The complete chart markdown block to insert (including the ```chart fences)'),
insertLocation: z.enum(['append', 'prepend']).default('append').describe('append: add to end, prepend: add to start'),
chartMarkdown: z.string().describe('The complete chart markdown block to render (including the ```chart fences)'),
}),
execute: async ({ noteId, chartMarkdown, insertLocation }) => {
try {
const note = await prisma.note.findFirst({
where: { id: noteId, userId: ctx.userId },
select: { content: true },
})
if (!note) return { error: 'Note not found' }
const updatedContent = insertLocation === 'append'
? `${note.content}\n\n${chartMarkdown}`
: `${chartMarkdown}\n\n${note.content}`
await prisma.note.update({
where: { id: noteId },
data: { content: updatedContent },
})
return {
success: true,
message: `Chart ${insertLocation === 'append' ? 'appended' : 'prepended'} to note.`,
chartMarkdown,
}
} catch (e: any) {
return { success: false, error: `Failed: ${e.message}` }
execute: async ({ chartMarkdown }) => {
return {
chartMarkdown,
message: 'Chart generated successfully',
}
},
}),
})
})

View File

@@ -13,6 +13,7 @@ export interface ToolContext {
actionId?: string
conversationId?: string
notebookId?: string
noteId?: string
webSearch?: boolean
config: Record<string, string>
}

View File

@@ -43,6 +43,21 @@ export const PALETTE_ALIASES: Record<string, string> = {
premium: 'platinum_white_gold', clean: 'vibrant_tech', stage: 'stage_dark',
architectural: 'architectural_mono', silk: 'minimal_silk',
black: 'keynote', white: 'platinum_white_gold', nuit: 'galaxy', sombre: 'stage_dark',
// Recipe explicit theme mappings
architectural_saas: 'architectural_mono',
midnight_cathedral: 'keynote',
aurora_borealis: 'galaxy',
tokyo_neon: 'vibrant_tech',
sunlit_gallery: 'bohemian',
clinical_precision: 'modern_wellness',
venture_pitch: 'vibrant_orange_mint',
forest_floor: 'forest_eco',
steel_glass: 'luxury_mystery',
cyberpunk_terminal: 'tech_night',
editorial_ink: 'vintage_academic',
coastal_morning: 'coastal_coral',
paper_studio: 'craft_artisan',
}
export const THEME_NAMES: Record<string, string> = {