Files
Momento/memento-note/lib/ai/tools/chart.tool.ts
Antigravity bfaacc557f
Some checks failed
CI / Lint, Test & Build (push) Failing after 15s
CI / Deploy production (on server) (push) Has been skipped
fix(chart): simplify to single insert_chart tool that does everything
2026-05-22 18:30:11 +00:00

85 lines
2.6 KiB
TypeScript

/**
* Chart Tool for Notes
* Allows AI to generate inline charts from note data
*/
import { tool } from 'ai'
import { z } from 'zod'
import { toolRegistry } from './registry'
import { prisma } from '@/lib/prisma'
// Simple chart insertion tool - does everything in one call
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.',
isInternal: true,
buildTool: (ctx) =>
tool({
description: `Generate a chart and insert it directly into the note content.
Available chart types:
- "bar": Vertical bar chart (default for comparisons)
- "horizontal-bar": Horizontal bar chart (use when labels are long)
- "line": Line chart (use for time series or trends)
- "area": Area chart (filled line chart)
- "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:
\`\`\`chart
{chartType}
{title}
{label1}: {value1}
{label2}: {value2}
...
\`\`\`
Example for "show sales by month":
\`\`\`chart
bar
Sales by Month
Jan: 5000
Feb: 7500
Mar: 6200
\`\`\`
4. Call this tool with the noteId, the chart markdown, and where to insert it`,
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'),
}),
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}` }
}
},
}),
})