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

@@ -90,11 +90,23 @@ export async function POST(req: Request) {
model: provider(model),
system: `You are a data visualization assistant. Analyze the provided text and suggest appropriate chart types.
CRITICAL: Extract ONLY numerical data present in the text. Do NOT invent values.
DATA EXTRACTION RULES:
- Extract ANY numerical data present in the text
- Look for patterns like: "X: 123", "X = 123", "X is 123", "X (123)", "123X", "X $123", "123%"
- Accept partial data (e.g., if only 2 values exist, that's still valid for a simple chart)
- If fewer than 2 data points exist, return hasData=false with empty suggestions
- Each suggestion must use the SAME extracted data (only chart type differs)
- Return exactly 3 suggestions when data exists
- Provide clear rationale for each chart type choice
CHART TYPE SELECTION:
- bar: Comparing values across categories (default choice)
- horizontal-bar: Categories with long labels
- line: Time series or sequential data
- area: Time series where magnitude matters
- pie: Parts of a whole (percentages or proportions)
- radar: Comparing multiple dimensions
- funnel: Stages or conversion steps
- gauge: Single value vs target
Response format (JSON):
{

View File

@@ -225,7 +225,25 @@ Only use tools if you need more information. Never invent note IDs or URLs.
- document_search: Searches attached PDF documents for the current note/notebook. Use when the user asks about documents or files.
- task_extract: Extracts action items from notes and creates a synthesis note. Use when the user asks to extract tasks or TODOs.
- note_find_and_update: Finds a note by search query and appends/prepends/replaces content. Use when the user says "find the note about X and add Y to it".
- insert_chart: Generates a chart (bar, line, area, pie, radar) and inserts it directly into the note. Use when the user asks "make a chart", "create a graph", "visualize this data", "show me a chart of X". Chart types: bar (comparisons), horizontal-bar (long labels), line/area (trends), pie (proportions), radar (comparisons).`,
- insert_chart: Generates a chart and inserts it directly into the note. Use when the user asks "make a chart", "create a graph", "visualize this data", "show me a chart of X".
IMPORTANT: Chart format MUST be exactly:
\`\`\`chart
{type}
{title}
{label}: {value}
{label}: {value}
\`\`\`
Example for sales chart:
\`\`\`chart
bar
Sales by Month
Jan: 5000
Feb: 7500
Mar: 6200
\`\`\`
Available types: bar, horizontal-bar, line, area, pie, radar. NEVER use Mermaid or other formats.`,
},
fr: {
contextWithNotes: `## Notes et documents de l'utilisateur\n\n${contextNotes}\n\nQuand tu utilises une info venant des notes ci-dessus, cite le titre de la note source entre parenthèses, ex: "Le déploiement se fait via Docker (💻 Development Guide)". Pour les documents PDF, cite le nom du fichier et la page, ex: "Le chiffre d'affaires est de 5M$ (📄 rapport.pdf p.12)". Ne recopie pas mot pour mot — reformule.`,
@@ -260,7 +278,25 @@ Tu as accès à : note_search, note_read, note_find_and_update, document_search,
- document_search : Recherche dans les documents PDF attachés à la note/au carnet.
- task_extract : Extrait les tâches/action items des notes et crée une note de synthèse.
- note_find_and_update : Trouve une note par recherche textuelle et ajoute/prépose/remplace du contenu. Utilise quand l'utilisateur dit "trouve la note sur X et ajoute-y Y".
- insert_chart : Génère un graphique (barres, ligne, aire, circulaire, radar) et l'insère directement dans la note. Utilise quand l'utilisateur demande "fais un graphique", "crée un chart", "visualise ces données", "montre-moi un chart de X". Types : bar (comparaisons), horizontal-bar (labels longs), line/area (tendances), pie (proportions), radar (comparaisons).`,
- insert_chart : Génère un graphique et l'insère directement dans la note. Utilise quand l'utilisateur demande "fais un graphique", "crée un chart", "visualise ces données".
IMPORTANT : Le format du graphique DOIT être exactement :
\`\`\`chart
{type}
{titre}
{label}: {valeur}
{label}: {valeur}
\`\`\`
Exemple pour un graphique de ventes :
\`\`\`chart
bar
Ventes par mois
Jan: 5000
Fév: 7500
Mar: 6200
\`\`\`
Types disponibles : bar, horizontal-bar, line, area, pie, radar. JAMAIS utiliser Mermaid ou d'autres formats.`,
},
fa: {
contextWithNotes: `## یادداشت‌های کاربر\n\n${contextNotes}\n\nهنگام استفاده از اطلاعات یادداشت‌های بالا، عنوان یادداشت منبع را در پرانتز ذکر کنید.`,
@@ -352,8 +388,17 @@ Focus ONLY on this note unless asked otherwise.`
}
const chatTools = noteContext
? toolRegistry.buildToolsForChat({ userId, config: sysConfig, webSearch, notebookId: notebookId || undefined })
: toolRegistry.buildToolsForChat({ userId, config: sysConfig, webSearch, notebookId: notebookId || undefined })
? toolRegistry.buildToolsForChat({ userId, config: sysConfig, webSearch, notebookId: notebookId || undefined, noteId })
: toolRegistry.buildToolsForChat({ userId, config: sysConfig, webSearch, notebookId: notebookId || undefined, noteId })
// Detect if user is asking for a chart/visualization to force tool usage
const lastMessage = currentMessage.toLowerCase()
const chartKeywords = [
'chart', 'graph', 'graphique', 'graphe', 'charte', 'visuali', 'diagramme',
'plot', 'courbe', 'histogram', 'bar', 'pie', 'line', 'area', 'radar',
'données', 'donnée', 'data', 'stat', 'mrr', 'arr', 'revenu', 'sales', 'vente'
]
const wantsChart = chartKeywords.some(k => lastMessage.includes(k))
const { result, usedByok } = await runLaneWithBillingUser(
'chat',
@@ -365,6 +410,7 @@ Focus ONLY on this note unless asked otherwise.`
system: systemPrompt,
messages: incomingMessages,
tools: chatTools,
toolChoice: wantsChart && chatTools.insert_chart ? { type: 'tool', toolName: 'insert_chart' } : undefined,
stopWhen: stepCountIs(5),
onFinish: async (final) => {
const userContent = incomingMessages[incomingMessages.length - 1].content

View File

@@ -110,10 +110,8 @@ export default async function RootLayout({
>
<head />
<body className={`${inter.className} ${inter.variable} ${manrope.variable} ${playfair.variable} ${jetbrainsMono.variable}`}>
<Script
id="theme-early"
strategy="worker"
dangerouslySetInnerHTML={{ __html: getThemeScript(userSettings.theme) }}
<script
dangerouslySetInnerHTML={{ __html: getThemeScript(userSettings.theme, userSettings.accentColor) }}
/>
<Script
id="sw-cleanup"