| import { tool } from "ai"; |
| import { z } from "zod"; |
|
|
| |
| |
| |
| |
| |
|
|
| export const embedTools = { |
| createEmbed: tool({ |
| description: |
| "Create or fully replace an HTML embed chart. Use when building a new chart from scratch " + |
| "or when changes are so extensive that a full rewrite is cleaner than patching. " + |
| "The HTML must be a self-contained fragment following D3 embed conventions " + |
| "(root div + scoped style + IIFE script).", |
| inputSchema: z.object({ |
| html: z |
| .string() |
| .describe( |
| "Complete self-contained HTML fragment (root div + scoped style + IIFE script)", |
| ), |
| title: z |
| .string() |
| .optional() |
| .describe("Short descriptive title for the chart"), |
| source: z |
| .string() |
| .optional() |
| .describe("Data source attribution"), |
| filename: z |
| .string() |
| .optional() |
| .describe( |
| "Descriptive file name slug for this chart, WITHOUT extension " + |
| "(e.g. 'attention-heatmap', 'model-accuracy', 'sales-by-region'). " + |
| "Use kebab-case, ASCII only, concise (2-4 words, <40 chars). " + |
| "REQUIRED on the first createEmbed call for a new chart - the " + |
| "client will slugify it, ensure uniqueness, and rename the file " + |
| "automatically. Omit on subsequent calls that only update the " + |
| "existing chart (the current name will be kept).", |
| ), |
| }), |
| }), |
|
|
| patchEmbed: tool({ |
| description: |
| "Replace a specific block of code in the current chart HTML. " + |
| "Use for targeted edits (color change, label update, data tweak, bug fix). " + |
| "Always prefer this over createEmbed when modifying an existing chart. " + |
| "The search string must be an exact verbatim excerpt from the current HTML " + |
| "(whitespace included). Call readEmbed first if unsure of the exact content.", |
| inputSchema: z.object({ |
| search: z |
| .string() |
| .describe( |
| "Exact verbatim excerpt from the current chart HTML to find and replace. " + |
| "Must be long enough to be unique (at least 3-5 lines of context).", |
| ), |
| replace: z |
| .string() |
| .describe("The new code that replaces the search block"), |
| }), |
| }), |
|
|
| readEmbed: tool({ |
| description: |
| "Read the full current chart HTML. Use before calling patchEmbed " + |
| "to verify the exact content, or to understand the current structure before editing.", |
| inputSchema: z.object({}), |
| }), |
|
|
| listDataFiles: tool({ |
| description: |
| "List all data files (CSV, TSV, JSON, NDJSON, TXT) the user has " + |
| "attached to this document. Returns one line per file with name, " + |
| "extension, size, row count, and column names when available. " + |
| "Call this when the user mentions data, a dataset, or wants to " + |
| "visualize content from a specific file.", |
| inputSchema: z.object({}), |
| }), |
|
|
| readDataFile: tool({ |
| description: |
| "Read the full raw content of a data file previously listed by " + |
| "listDataFiles. Use this to inspect the exact structure, sample " + |
| "values, or to embed small datasets directly into the chart. Large " + |
| "files may be truncated - prefer loading via fetch from " + |
| "/data/<name> for charts that rely on the full dataset.", |
| inputSchema: z.object({ |
| name: z |
| .string() |
| .describe("Exact file name as returned by listDataFiles (e.g. 'sales.csv')"), |
| }), |
| }), |
| }; |
|
|