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:
@@ -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):
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user