@sqlrooms/vega 0.29.0-rc.1 → 0.29.0-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +2 -1
- package/README.md +23 -0
- package/dist/ChartImageForMarkdownTool.d.ts +84 -0
- package/dist/ChartImageForMarkdownTool.d.ts.map +1 -0
- package/dist/ChartImageForMarkdownTool.js +287 -0
- package/dist/ChartImageForMarkdownTool.js.map +1 -0
- package/dist/VegaChartActions.js +1 -1
- package/dist/VegaChartActions.js.map +1 -1
- package/dist/VegaChartTool.d.ts +47 -26
- package/dist/VegaChartTool.d.ts.map +1 -1
- package/dist/VegaChartTool.js +61 -35
- package/dist/VegaChartTool.js.map +1 -1
- package/dist/VegaChartToolResult.d.ts +8 -20
- package/dist/VegaChartToolResult.d.ts.map +1 -1
- package/dist/VegaChartToolResult.js +8 -34
- package/dist/VegaChartToolResult.js.map +1 -1
- package/dist/VegaEditAction.d.ts +4 -9
- package/dist/VegaEditAction.d.ts.map +1 -1
- package/dist/VegaEditAction.js +9 -12
- package/dist/VegaEditAction.js.map +1 -1
- package/dist/VegaLiteArrowChart.d.ts.map +1 -1
- package/dist/VegaLiteArrowChart.js +8 -3
- package/dist/VegaLiteArrowChart.js.map +1 -1
- package/dist/VegaLiteSqlChart.js +1 -1
- package/dist/VegaLiteSqlChart.js.map +1 -1
- package/dist/editor/VegaChartDisplay.js +1 -1
- package/dist/editor/VegaChartDisplay.js.map +1 -1
- package/dist/editor/VegaCodeMirrorEditor.d.ts +15 -0
- package/dist/editor/VegaCodeMirrorEditor.d.ts.map +1 -0
- package/dist/editor/VegaCodeMirrorEditor.js +23 -0
- package/dist/editor/VegaCodeMirrorEditor.js.map +1 -0
- package/dist/editor/VegaMonacoEditor.d.ts +5 -0
- package/dist/editor/VegaMonacoEditor.d.ts.map +1 -1
- package/dist/editor/VegaMonacoEditor.js +2 -0
- package/dist/editor/VegaMonacoEditor.js.map +1 -1
- package/dist/editor/VegaSpecEditorPanel.d.ts.map +1 -1
- package/dist/editor/VegaSpecEditorPanel.js +11 -7
- package/dist/editor/VegaSpecEditorPanel.js.map +1 -1
- package/dist/editor/VegaSqlEditorPanel.d.ts +1 -1
- package/dist/editor/VegaSqlEditorPanel.d.ts.map +1 -1
- package/dist/editor/VegaSqlEditorPanel.js +9 -10
- package/dist/editor/VegaSqlEditorPanel.js.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/package.json +27 -25
package/LICENSE.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright
|
|
3
|
+
Copyright 2024-2026 SQLRooms Contributors
|
|
4
|
+
Copyright Vis.gl contributors
|
|
4
5
|
|
|
5
6
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
7
|
|
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ npm install @sqlrooms/vega @sqlrooms/duckdb @sqlrooms/ui
|
|
|
10
10
|
|
|
11
11
|
- `VegaLiteChart` (simple + compound component API)
|
|
12
12
|
- `createVegaChartTool()` for AI tool workflows
|
|
13
|
+
- `createChartImageForMarkdownTool()` for AI-generated Markdown document image assets
|
|
13
14
|
- `VegaChartToolResult`
|
|
14
15
|
- editor utilities/hooks (`useVegaChartEditor`, `useVegaEditorContext`)
|
|
15
16
|
|
|
@@ -104,6 +105,28 @@ These fields are supplied by the LLM when invoking the tool (not passed into
|
|
|
104
105
|
- `vegaLiteSpec`: Vega-Lite JSON string
|
|
105
106
|
- `reasoning`: explanation shown to users for why this chart/spec was chosen
|
|
106
107
|
|
|
108
|
+
## Markdown document image assets
|
|
109
|
+
|
|
110
|
+
`createChartImageForMarkdownTool(store)` creates an AI-only companion tool that
|
|
111
|
+
renders a Vega chart to SVG or PNG, stores it as an asset on a
|
|
112
|
+
`@sqlrooms/documents` Markdown artifact, and returns a ready-to-insert Markdown
|
|
113
|
+
image link such as:
|
|
114
|
+
|
|
115
|
+
```md
|
|
116
|
+

|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Use this alongside the existing document commands when the assistant needs a
|
|
120
|
+
portable conversation summary with static chart images instead of live SQL-backed
|
|
121
|
+
charts.
|
|
122
|
+
|
|
123
|
+
Chart images default to the light Vega theme with an explicit background so
|
|
124
|
+
exported Markdown renders predictably in GitHub, Obsidian, PDF exports, and
|
|
125
|
+
other document surfaces. When the requested static theme matches the current app
|
|
126
|
+
theme, the background is resolved from the app's Tailwind `--background` token
|
|
127
|
+
and written into the SVG/PNG as a concrete color. The tool also accepts
|
|
128
|
+
`renderTheme: "dark"` and `background` for explicit dark/static export requests.
|
|
129
|
+
|
|
107
130
|
## Example apps
|
|
108
131
|
|
|
109
132
|
- Vega example: https://github.com/sqlrooms/examples/tree/main/vega
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { AiSliceState } from '@sqlrooms/ai-core';
|
|
2
|
+
import type { DocumentsSliceState } from '@sqlrooms/documents';
|
|
3
|
+
import { type DuckDbSliceState } from '@sqlrooms/duckdb';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
export declare const ChartImageForMarkdownToolParameters: z.ZodObject<{
|
|
6
|
+
documentArtifactId: z.ZodString;
|
|
7
|
+
sourceToolCallId: z.ZodOptional<z.ZodString>;
|
|
8
|
+
sqlQuery: z.ZodOptional<z.ZodString>;
|
|
9
|
+
vegaLiteSpec: z.ZodOptional<z.ZodString>;
|
|
10
|
+
format: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
11
|
+
svg: "svg";
|
|
12
|
+
png: "png";
|
|
13
|
+
}>>>;
|
|
14
|
+
assetId: z.ZodOptional<z.ZodString>;
|
|
15
|
+
alt: z.ZodString;
|
|
16
|
+
title: z.ZodOptional<z.ZodString>;
|
|
17
|
+
width: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
18
|
+
height: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
19
|
+
pngScale: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
20
|
+
renderTheme: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
21
|
+
light: "light";
|
|
22
|
+
dark: "dark";
|
|
23
|
+
}>>>;
|
|
24
|
+
background: z.ZodOptional<z.ZodString>;
|
|
25
|
+
}, z.core.$strip>;
|
|
26
|
+
export type ChartImageForMarkdownToolParameters = z.infer<typeof ChartImageForMarkdownToolParameters>;
|
|
27
|
+
export type ChartImageForMarkdownToolOutput = {
|
|
28
|
+
success: boolean;
|
|
29
|
+
details: string;
|
|
30
|
+
documentArtifactId: string;
|
|
31
|
+
assetId?: string;
|
|
32
|
+
markdown?: string;
|
|
33
|
+
mediaType?: 'image/svg+xml' | 'image/png';
|
|
34
|
+
encoding?: 'utf8' | 'base64';
|
|
35
|
+
format?: 'svg' | 'png';
|
|
36
|
+
renderTheme?: 'light' | 'dark';
|
|
37
|
+
background?: string;
|
|
38
|
+
error?: string;
|
|
39
|
+
};
|
|
40
|
+
type StoreLike<S> = {
|
|
41
|
+
getState: () => S;
|
|
42
|
+
};
|
|
43
|
+
type ChartImageToolState = AiSliceState & DuckDbSliceState & DocumentsSliceState;
|
|
44
|
+
export declare function createChartImageForMarkdownTool<S extends ChartImageToolState = ChartImageToolState>(store: StoreLike<S>): import("ai").Tool<{
|
|
45
|
+
documentArtifactId: string;
|
|
46
|
+
format: "svg" | "png";
|
|
47
|
+
alt: string;
|
|
48
|
+
width: number;
|
|
49
|
+
height: number;
|
|
50
|
+
pngScale: number;
|
|
51
|
+
renderTheme: "light" | "dark";
|
|
52
|
+
sourceToolCallId?: string | undefined;
|
|
53
|
+
sqlQuery?: string | undefined;
|
|
54
|
+
vegaLiteSpec?: string | undefined;
|
|
55
|
+
assetId?: string | undefined;
|
|
56
|
+
title?: string | undefined;
|
|
57
|
+
background?: string | undefined;
|
|
58
|
+
}, {
|
|
59
|
+
success: false;
|
|
60
|
+
details: string;
|
|
61
|
+
documentArtifactId: string;
|
|
62
|
+
error: string;
|
|
63
|
+
assetId?: undefined;
|
|
64
|
+
markdown?: undefined;
|
|
65
|
+
mediaType?: undefined;
|
|
66
|
+
encoding?: undefined;
|
|
67
|
+
format?: undefined;
|
|
68
|
+
renderTheme?: undefined;
|
|
69
|
+
background?: undefined;
|
|
70
|
+
} | {
|
|
71
|
+
success: true;
|
|
72
|
+
details: string;
|
|
73
|
+
documentArtifactId: string;
|
|
74
|
+
assetId: string;
|
|
75
|
+
markdown: string;
|
|
76
|
+
mediaType: "image/svg+xml" | "image/png";
|
|
77
|
+
encoding: "utf8" | "base64";
|
|
78
|
+
format: "svg" | "png";
|
|
79
|
+
renderTheme: "light" | "dark";
|
|
80
|
+
background: string;
|
|
81
|
+
error?: undefined;
|
|
82
|
+
}>;
|
|
83
|
+
export {};
|
|
84
|
+
//# sourceMappingURL=ChartImageForMarkdownTool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChartImageForMarkdownTool.d.ts","sourceRoot":"","sources":["../src/ChartImageForMarkdownTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAmB,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAIzE,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAStB,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;;;;;iBA6C7C,CAAC;AAEJ,MAAM,MAAM,mCAAmC,GAAG,CAAC,CAAC,KAAK,CACvD,OAAO,mCAAmC,CAC3C,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,eAAe,GAAG,WAAW,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7B,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,SAAS,CAAC,CAAC,IAAI;IAClB,QAAQ,EAAE,MAAM,CAAC,CAAC;CACnB,CAAC;AAEF,KAAK,mBAAmB,GAAG,YAAY,GACrC,gBAAgB,GAChB,mBAAmB,CAAC;AAEtB,wBAAgB,+BAA+B,CAC7C,CAAC,SAAS,mBAAmB,GAAG,mBAAmB,EACnD,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0FpB"}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { arrowTableToJson } from '@sqlrooms/duckdb';
|
|
2
|
+
import { tool } from 'ai';
|
|
3
|
+
import { parse as vegaParse, View } from 'vega';
|
|
4
|
+
import { compile } from 'vega-lite';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { darkTheme } from './themes/darkTheme';
|
|
7
|
+
import { lightTheme } from './themes/lightTheme';
|
|
8
|
+
const TAILWIND_BACKGROUND_VARIABLE = '--background';
|
|
9
|
+
const FALLBACK_LIGHT_BACKGROUND = '#ffffff';
|
|
10
|
+
const FALLBACK_DARK_BACKGROUND = 'oklch(0.145 0 0)';
|
|
11
|
+
export const ChartImageForMarkdownToolParameters = z
|
|
12
|
+
.object({
|
|
13
|
+
documentArtifactId: z
|
|
14
|
+
.string()
|
|
15
|
+
.describe('Target Markdown document artifact ID.'),
|
|
16
|
+
sourceToolCallId: z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe('Prior successful chart tool call ID to render.'),
|
|
20
|
+
sqlQuery: z
|
|
21
|
+
.string()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe('SQL query to render when no sourceToolCallId is provided.'),
|
|
24
|
+
vegaLiteSpec: z
|
|
25
|
+
.string()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe('Vega-Lite JSON spec string without inline data.'),
|
|
28
|
+
format: z.enum(['svg', 'png']).optional().default('svg'),
|
|
29
|
+
assetId: z.string().optional().describe('Stable document-local asset ID.'),
|
|
30
|
+
alt: z.string().describe('Markdown image alt text.'),
|
|
31
|
+
title: z.string().optional().describe('Optional image title.'),
|
|
32
|
+
width: z.number().positive().optional().default(960),
|
|
33
|
+
height: z.number().positive().optional().default(540),
|
|
34
|
+
pngScale: z.number().positive().optional().default(2),
|
|
35
|
+
renderTheme: z
|
|
36
|
+
.enum(['light', 'dark'])
|
|
37
|
+
.optional()
|
|
38
|
+
.default('light')
|
|
39
|
+
.describe('Static chart theme for the rendered image. Defaults to light for portable Markdown documents.'),
|
|
40
|
+
background: z
|
|
41
|
+
.string()
|
|
42
|
+
.optional()
|
|
43
|
+
.describe('CSS color used as the exported image background. Defaults to the resolved Tailwind --background token for the requested theme when available.'),
|
|
44
|
+
})
|
|
45
|
+
.refine((input) => Boolean(input.sourceToolCallId) ||
|
|
46
|
+
(Boolean(input.sqlQuery) && Boolean(input.vegaLiteSpec)), {
|
|
47
|
+
message: 'Provide sourceToolCallId or both sqlQuery and vegaLiteSpec.',
|
|
48
|
+
});
|
|
49
|
+
export function createChartImageForMarkdownTool(store) {
|
|
50
|
+
return tool({
|
|
51
|
+
description: `Render an existing Vega chart analysis as a static SVG or PNG image asset for a Markdown document.
|
|
52
|
+
Use this before embedding chart images in document artifacts. The tool stores the image in the target document and returns a Markdown image link using asset://.
|
|
53
|
+
For portable Markdown documents, the default renderTheme is light with a white background. Only request dark rendering when the user explicitly wants a dark static image.`,
|
|
54
|
+
inputSchema: ChartImageForMarkdownToolParameters,
|
|
55
|
+
execute: async (params, options) => {
|
|
56
|
+
const abortSignal = options?.abortSignal;
|
|
57
|
+
try {
|
|
58
|
+
const source = resolveChartSource(store.getState(), params);
|
|
59
|
+
if (!source.success) {
|
|
60
|
+
return {
|
|
61
|
+
success: false,
|
|
62
|
+
details: source.error,
|
|
63
|
+
documentArtifactId: params.documentArtifactId,
|
|
64
|
+
error: source.error,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const connector = await store.getState().db.getConnector();
|
|
68
|
+
const queryResult = await connector.query(source.sqlQuery, {
|
|
69
|
+
signal: abortSignal,
|
|
70
|
+
});
|
|
71
|
+
if (abortSignal?.aborted) {
|
|
72
|
+
throw new Error('Chart image rendering was aborted');
|
|
73
|
+
}
|
|
74
|
+
const values = arrowTableToJson(queryResult);
|
|
75
|
+
const image = await renderVegaLiteImage({
|
|
76
|
+
spec: source.vegaLiteSpec,
|
|
77
|
+
values,
|
|
78
|
+
format: params.format,
|
|
79
|
+
width: params.width,
|
|
80
|
+
height: params.height,
|
|
81
|
+
pngScale: params.pngScale,
|
|
82
|
+
renderTheme: params.renderTheme,
|
|
83
|
+
background: resolveRenderBackground(params),
|
|
84
|
+
});
|
|
85
|
+
const timestamp = Date.now();
|
|
86
|
+
const assetId = params.assetId ?? createChartAssetId(params, source.sourceToolCallId);
|
|
87
|
+
const filename = `${assetId}.${params.format}`;
|
|
88
|
+
store.getState().documents.upsertAsset(params.documentArtifactId, {
|
|
89
|
+
id: assetId,
|
|
90
|
+
mediaType: image.mediaType,
|
|
91
|
+
encoding: image.encoding,
|
|
92
|
+
data: image.data,
|
|
93
|
+
filename,
|
|
94
|
+
alt: params.alt,
|
|
95
|
+
title: params.title,
|
|
96
|
+
provenance: {
|
|
97
|
+
sourceToolCallId: source.sourceToolCallId,
|
|
98
|
+
sqlQuery: source.sqlQuery,
|
|
99
|
+
vegaLiteSpec: source.vegaLiteSpec,
|
|
100
|
+
renderTheme: params.renderTheme,
|
|
101
|
+
background: image.background,
|
|
102
|
+
renderedAt: new Date(timestamp).toISOString(),
|
|
103
|
+
},
|
|
104
|
+
createdAt: timestamp,
|
|
105
|
+
updatedAt: timestamp,
|
|
106
|
+
});
|
|
107
|
+
return {
|
|
108
|
+
success: true,
|
|
109
|
+
details: `Stored ${params.format.toUpperCase()} chart image asset "${assetId}" in document "${params.documentArtifactId}".`,
|
|
110
|
+
documentArtifactId: params.documentArtifactId,
|
|
111
|
+
assetId,
|
|
112
|
+
markdown: `})`,
|
|
113
|
+
mediaType: image.mediaType,
|
|
114
|
+
encoding: image.encoding,
|
|
115
|
+
format: params.format,
|
|
116
|
+
renderTheme: params.renderTheme,
|
|
117
|
+
background: image.background,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
122
|
+
return {
|
|
123
|
+
success: false,
|
|
124
|
+
details: `Failed to render chart image: ${message}`,
|
|
125
|
+
documentArtifactId: params.documentArtifactId,
|
|
126
|
+
error: message,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
toModelOutput: ({ output }) => ({
|
|
131
|
+
type: 'text',
|
|
132
|
+
value: JSON.stringify(output),
|
|
133
|
+
}),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function resolveChartSource(state, params) {
|
|
137
|
+
if (params.sourceToolCallId) {
|
|
138
|
+
const output = findChartToolOutput(state, params.sourceToolCallId);
|
|
139
|
+
if (!output) {
|
|
140
|
+
return {
|
|
141
|
+
success: false,
|
|
142
|
+
error: `No successful chart tool call found for "${params.sourceToolCallId}".`,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (!output.sqlQuery || !output.vegaLiteSpec) {
|
|
146
|
+
return {
|
|
147
|
+
success: false,
|
|
148
|
+
error: `Chart tool call "${params.sourceToolCallId}" has no renderable SQL query or Vega-Lite spec.`,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
success: true,
|
|
153
|
+
sqlQuery: output.sqlQuery,
|
|
154
|
+
vegaLiteSpec: output.vegaLiteSpec,
|
|
155
|
+
sourceToolCallId: params.sourceToolCallId,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
if (!params.sqlQuery || !params.vegaLiteSpec) {
|
|
159
|
+
return {
|
|
160
|
+
success: false,
|
|
161
|
+
error: 'Provide sourceToolCallId or both sqlQuery and vegaLiteSpec.',
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
return {
|
|
166
|
+
success: true,
|
|
167
|
+
sqlQuery: params.sqlQuery,
|
|
168
|
+
vegaLiteSpec: JSON.parse(params.vegaLiteSpec),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
return {
|
|
173
|
+
success: false,
|
|
174
|
+
error: `Invalid Vega-Lite JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function findChartToolOutput(state, sourceToolCallId) {
|
|
179
|
+
const currentSession = state.ai.getCurrentSession();
|
|
180
|
+
const messages = currentSession?.uiMessages ?? [];
|
|
181
|
+
for (const message of messages) {
|
|
182
|
+
if (message.role !== 'assistant')
|
|
183
|
+
continue;
|
|
184
|
+
for (const part of message.parts) {
|
|
185
|
+
if (!('toolCallId' in part) || part.toolCallId !== sourceToolCallId) {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (part.state === 'output-available' &&
|
|
189
|
+
'output' in part &&
|
|
190
|
+
isVegaChartToolOutput(part.output)) {
|
|
191
|
+
return part.output;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
function isVegaChartToolOutput(value) {
|
|
198
|
+
return (typeof value === 'object' &&
|
|
199
|
+
value !== null &&
|
|
200
|
+
'success' in value &&
|
|
201
|
+
value.success === true &&
|
|
202
|
+
'sqlQuery' in value &&
|
|
203
|
+
'vegaLiteSpec' in value);
|
|
204
|
+
}
|
|
205
|
+
async function renderVegaLiteImage({ spec, values, format, width, height, pngScale, renderTheme, background, }) {
|
|
206
|
+
const themeConfig = renderTheme === 'dark' ? darkTheme : lightTheme;
|
|
207
|
+
const specWithData = {
|
|
208
|
+
padding: 10,
|
|
209
|
+
...spec,
|
|
210
|
+
background,
|
|
211
|
+
config: {
|
|
212
|
+
...themeConfig,
|
|
213
|
+
...(spec.config ?? {}),
|
|
214
|
+
background,
|
|
215
|
+
},
|
|
216
|
+
data: { values },
|
|
217
|
+
width,
|
|
218
|
+
height,
|
|
219
|
+
autosize: { contains: 'padding' },
|
|
220
|
+
};
|
|
221
|
+
const compiled = compile(specWithData).spec;
|
|
222
|
+
const view = new View(vegaParse(compiled), {
|
|
223
|
+
renderer: format === 'png' ? 'canvas' : 'none',
|
|
224
|
+
});
|
|
225
|
+
try {
|
|
226
|
+
await view.runAsync();
|
|
227
|
+
if (format === 'svg') {
|
|
228
|
+
return {
|
|
229
|
+
mediaType: 'image/svg+xml',
|
|
230
|
+
encoding: 'utf8',
|
|
231
|
+
background,
|
|
232
|
+
data: await view.toSVG(),
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
const canvas = await view.toCanvas(pngScale);
|
|
236
|
+
return {
|
|
237
|
+
mediaType: 'image/png',
|
|
238
|
+
encoding: 'base64',
|
|
239
|
+
background,
|
|
240
|
+
data: await canvasToBase64(canvas),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
finally {
|
|
244
|
+
view.finalize();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async function canvasToBase64(canvas) {
|
|
248
|
+
const dataUrl = canvas.toDataURL('image/png');
|
|
249
|
+
return dataUrl.replace(/^data:image\/png;base64,/, '');
|
|
250
|
+
}
|
|
251
|
+
function createChartAssetId(params, sourceToolCallId) {
|
|
252
|
+
const base = params.title || params.alt || sourceToolCallId || 'chart';
|
|
253
|
+
const slug = base
|
|
254
|
+
.toLowerCase()
|
|
255
|
+
.trim()
|
|
256
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
257
|
+
.replace(/^-+|-+$/g, '')
|
|
258
|
+
.slice(0, 48);
|
|
259
|
+
return `${slug || 'chart'}-${Date.now().toString(36)}`;
|
|
260
|
+
}
|
|
261
|
+
function escapeMarkdownAlt(value) {
|
|
262
|
+
return value.replace(/]/g, '\\]');
|
|
263
|
+
}
|
|
264
|
+
function resolveRenderBackground(params) {
|
|
265
|
+
if (params.background)
|
|
266
|
+
return params.background;
|
|
267
|
+
const tailwindBackground = resolveTailwindBackgroundForTheme(params.renderTheme);
|
|
268
|
+
if (tailwindBackground)
|
|
269
|
+
return tailwindBackground;
|
|
270
|
+
return params.renderTheme === 'dark'
|
|
271
|
+
? FALLBACK_DARK_BACKGROUND
|
|
272
|
+
: FALLBACK_LIGHT_BACKGROUND;
|
|
273
|
+
}
|
|
274
|
+
function resolveTailwindBackgroundForTheme(renderTheme) {
|
|
275
|
+
if (typeof document === 'undefined')
|
|
276
|
+
return undefined;
|
|
277
|
+
const currentTheme = document.documentElement.classList.contains('dark')
|
|
278
|
+
? 'dark'
|
|
279
|
+
: 'light';
|
|
280
|
+
if (currentTheme !== renderTheme)
|
|
281
|
+
return undefined;
|
|
282
|
+
const value = getComputedStyle(document.documentElement)
|
|
283
|
+
.getPropertyValue(TAILWIND_BACKGROUND_VARIABLE)
|
|
284
|
+
.trim();
|
|
285
|
+
return value || undefined;
|
|
286
|
+
}
|
|
287
|
+
//# sourceMappingURL=ChartImageForMarkdownTool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChartImageForMarkdownTool.js","sourceRoot":"","sources":["../src/ChartImageForMarkdownTool.ts"],"names":[],"mappings":"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","sourcesContent":["import type {AiSliceState} from '@sqlrooms/ai-core';\nimport type {DocumentsSliceState} from '@sqlrooms/documents';\nimport {arrowTableToJson, type DuckDbSliceState} from '@sqlrooms/duckdb';\nimport {tool} from 'ai';\nimport {parse as vegaParse, View} from 'vega';\nimport {compile, type TopLevelSpec} from 'vega-lite';\nimport {z} from 'zod';\nimport {darkTheme} from './themes/darkTheme';\nimport {lightTheme} from './themes/lightTheme';\nimport type {VegaChartToolOutput} from './VegaChartTool';\n\nconst TAILWIND_BACKGROUND_VARIABLE = '--background';\nconst FALLBACK_LIGHT_BACKGROUND = '#ffffff';\nconst FALLBACK_DARK_BACKGROUND = 'oklch(0.145 0 0)';\n\nexport const ChartImageForMarkdownToolParameters = z\n .object({\n documentArtifactId: z\n .string()\n .describe('Target Markdown document artifact ID.'),\n sourceToolCallId: z\n .string()\n .optional()\n .describe('Prior successful chart tool call ID to render.'),\n sqlQuery: z\n .string()\n .optional()\n .describe('SQL query to render when no sourceToolCallId is provided.'),\n vegaLiteSpec: z\n .string()\n .optional()\n .describe('Vega-Lite JSON spec string without inline data.'),\n format: z.enum(['svg', 'png']).optional().default('svg'),\n assetId: z.string().optional().describe('Stable document-local asset ID.'),\n alt: z.string().describe('Markdown image alt text.'),\n title: z.string().optional().describe('Optional image title.'),\n width: z.number().positive().optional().default(960),\n height: z.number().positive().optional().default(540),\n pngScale: z.number().positive().optional().default(2),\n renderTheme: z\n .enum(['light', 'dark'])\n .optional()\n .default('light')\n .describe(\n 'Static chart theme for the rendered image. Defaults to light for portable Markdown documents.',\n ),\n background: z\n .string()\n .optional()\n .describe(\n 'CSS color used as the exported image background. Defaults to the resolved Tailwind --background token for the requested theme when available.',\n ),\n })\n .refine(\n (input) =>\n Boolean(input.sourceToolCallId) ||\n (Boolean(input.sqlQuery) && Boolean(input.vegaLiteSpec)),\n {\n message: 'Provide sourceToolCallId or both sqlQuery and vegaLiteSpec.',\n },\n );\n\nexport type ChartImageForMarkdownToolParameters = z.infer<\n typeof ChartImageForMarkdownToolParameters\n>;\n\nexport type ChartImageForMarkdownToolOutput = {\n success: boolean;\n details: string;\n documentArtifactId: string;\n assetId?: string;\n markdown?: string;\n mediaType?: 'image/svg+xml' | 'image/png';\n encoding?: 'utf8' | 'base64';\n format?: 'svg' | 'png';\n renderTheme?: 'light' | 'dark';\n background?: string;\n error?: string;\n};\n\ntype StoreLike<S> = {\n getState: () => S;\n};\n\ntype ChartImageToolState = AiSliceState &\n DuckDbSliceState &\n DocumentsSliceState;\n\nexport function createChartImageForMarkdownTool<\n S extends ChartImageToolState = ChartImageToolState,\n>(store: StoreLike<S>) {\n return tool({\n description: `Render an existing Vega chart analysis as a static SVG or PNG image asset for a Markdown document.\nUse this before embedding chart images in document artifacts. The tool stores the image in the target document and returns a Markdown image link using asset://.\nFor portable Markdown documents, the default renderTheme is light with a white background. Only request dark rendering when the user explicitly wants a dark static image.`,\n inputSchema: ChartImageForMarkdownToolParameters,\n execute: async (params, options) => {\n const abortSignal = options?.abortSignal;\n try {\n const source = resolveChartSource(store.getState(), params);\n if (!source.success) {\n return {\n success: false,\n details: source.error,\n documentArtifactId: params.documentArtifactId,\n error: source.error,\n } satisfies ChartImageForMarkdownToolOutput;\n }\n\n const connector = await store.getState().db.getConnector();\n const queryResult = await connector.query(source.sqlQuery, {\n signal: abortSignal,\n });\n if (abortSignal?.aborted) {\n throw new Error('Chart image rendering was aborted');\n }\n\n const values = arrowTableToJson(queryResult);\n const image = await renderVegaLiteImage({\n spec: source.vegaLiteSpec,\n values,\n format: params.format,\n width: params.width,\n height: params.height,\n pngScale: params.pngScale,\n renderTheme: params.renderTheme,\n background: resolveRenderBackground(params),\n });\n const timestamp = Date.now();\n const assetId =\n params.assetId ?? createChartAssetId(params, source.sourceToolCallId);\n const filename = `${assetId}.${params.format}`;\n\n store.getState().documents.upsertAsset(params.documentArtifactId, {\n id: assetId,\n mediaType: image.mediaType,\n encoding: image.encoding,\n data: image.data,\n filename,\n alt: params.alt,\n title: params.title,\n provenance: {\n sourceToolCallId: source.sourceToolCallId,\n sqlQuery: source.sqlQuery,\n vegaLiteSpec: source.vegaLiteSpec,\n renderTheme: params.renderTheme,\n background: image.background,\n renderedAt: new Date(timestamp).toISOString(),\n },\n createdAt: timestamp,\n updatedAt: timestamp,\n });\n\n return {\n success: true,\n details: `Stored ${params.format.toUpperCase()} chart image asset \"${assetId}\" in document \"${params.documentArtifactId}\".`,\n documentArtifactId: params.documentArtifactId,\n assetId,\n markdown: `})`,\n mediaType: image.mediaType,\n encoding: image.encoding,\n format: params.format,\n renderTheme: params.renderTheme,\n background: image.background,\n } satisfies ChartImageForMarkdownToolOutput;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n details: `Failed to render chart image: ${message}`,\n documentArtifactId: params.documentArtifactId,\n error: message,\n } satisfies ChartImageForMarkdownToolOutput;\n }\n },\n toModelOutput: ({output}) => ({\n type: 'text',\n value: JSON.stringify(output),\n }),\n });\n}\n\nfunction resolveChartSource(\n state: ChartImageToolState,\n params: ChartImageForMarkdownToolParameters,\n):\n | {\n success: true;\n sqlQuery: string;\n vegaLiteSpec: TopLevelSpec;\n sourceToolCallId?: string;\n }\n | {success: false; error: string} {\n if (params.sourceToolCallId) {\n const output = findChartToolOutput(state, params.sourceToolCallId);\n if (!output) {\n return {\n success: false,\n error: `No successful chart tool call found for \"${params.sourceToolCallId}\".`,\n };\n }\n if (!output.sqlQuery || !output.vegaLiteSpec) {\n return {\n success: false,\n error: `Chart tool call \"${params.sourceToolCallId}\" has no renderable SQL query or Vega-Lite spec.`,\n };\n }\n return {\n success: true,\n sqlQuery: output.sqlQuery,\n vegaLiteSpec: output.vegaLiteSpec,\n sourceToolCallId: params.sourceToolCallId,\n };\n }\n\n if (!params.sqlQuery || !params.vegaLiteSpec) {\n return {\n success: false,\n error: 'Provide sourceToolCallId or both sqlQuery and vegaLiteSpec.',\n };\n }\n\n try {\n return {\n success: true,\n sqlQuery: params.sqlQuery,\n vegaLiteSpec: JSON.parse(params.vegaLiteSpec) as TopLevelSpec,\n };\n } catch (error) {\n return {\n success: false,\n error: `Invalid Vega-Lite JSON: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n}\n\nfunction findChartToolOutput(\n state: ChartImageToolState,\n sourceToolCallId: string,\n): VegaChartToolOutput | undefined {\n const currentSession = state.ai.getCurrentSession();\n const messages = currentSession?.uiMessages ?? [];\n for (const message of messages) {\n if (message.role !== 'assistant') continue;\n for (const part of message.parts) {\n if (!('toolCallId' in part) || part.toolCallId !== sourceToolCallId) {\n continue;\n }\n if (\n part.state === 'output-available' &&\n 'output' in part &&\n isVegaChartToolOutput(part.output)\n ) {\n return part.output;\n }\n }\n }\n return undefined;\n}\n\nfunction isVegaChartToolOutput(value: unknown): value is VegaChartToolOutput {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'success' in value &&\n (value as VegaChartToolOutput).success === true &&\n 'sqlQuery' in value &&\n 'vegaLiteSpec' in value\n );\n}\n\nasync function renderVegaLiteImage({\n spec,\n values,\n format,\n width,\n height,\n pngScale,\n renderTheme,\n background,\n}: {\n spec: TopLevelSpec;\n values: Record<string, unknown>[];\n format: 'svg' | 'png';\n width: number;\n height: number;\n pngScale: number;\n renderTheme: 'light' | 'dark';\n background: string;\n}) {\n const themeConfig = renderTheme === 'dark' ? darkTheme : lightTheme;\n const specWithData = {\n padding: 10,\n ...spec,\n background,\n config: {\n ...themeConfig,\n ...(spec.config ?? {}),\n background,\n },\n data: {values},\n width,\n height,\n autosize: {contains: 'padding'},\n } as TopLevelSpec;\n const compiled = compile(specWithData).spec;\n const view = new View(vegaParse(compiled), {\n renderer: format === 'png' ? 'canvas' : 'none',\n });\n\n try {\n await view.runAsync();\n if (format === 'svg') {\n return {\n mediaType: 'image/svg+xml' as const,\n encoding: 'utf8' as const,\n background,\n data: await view.toSVG(),\n };\n }\n const canvas = await view.toCanvas(pngScale);\n return {\n mediaType: 'image/png' as const,\n encoding: 'base64' as const,\n background,\n data: await canvasToBase64(canvas),\n };\n } finally {\n view.finalize();\n }\n}\n\nasync function canvasToBase64(canvas: HTMLCanvasElement) {\n const dataUrl = canvas.toDataURL('image/png');\n return dataUrl.replace(/^data:image\\/png;base64,/, '');\n}\n\nfunction createChartAssetId(\n params: ChartImageForMarkdownToolParameters,\n sourceToolCallId?: string,\n) {\n const base = params.title || params.alt || sourceToolCallId || 'chart';\n const slug = base\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 48);\n return `${slug || 'chart'}-${Date.now().toString(36)}`;\n}\n\nfunction escapeMarkdownAlt(value: string) {\n return value.replace(/]/g, '\\\\]');\n}\n\nfunction resolveRenderBackground(params: ChartImageForMarkdownToolParameters) {\n if (params.background) return params.background;\n const tailwindBackground = resolveTailwindBackgroundForTheme(\n params.renderTheme,\n );\n if (tailwindBackground) return tailwindBackground;\n return params.renderTheme === 'dark'\n ? FALLBACK_DARK_BACKGROUND\n : FALLBACK_LIGHT_BACKGROUND;\n}\n\nfunction resolveTailwindBackgroundForTheme(renderTheme: 'light' | 'dark') {\n if (typeof document === 'undefined') return undefined;\n const currentTheme = document.documentElement.classList.contains('dark')\n ? 'dark'\n : 'light';\n if (currentTheme !== renderTheme) return undefined;\n\n const value = getComputedStyle(document.documentElement)\n .getPropertyValue(TAILWIND_BACKGROUND_VARIABLE)\n .trim();\n return value || undefined;\n}\n"]}
|
package/dist/VegaChartActions.js
CHANGED
|
@@ -18,6 +18,6 @@ import { cn } from '@sqlrooms/ui';
|
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
20
|
export const VegaChartActions = ({ children, className, }) => {
|
|
21
|
-
return (_jsx("div", { className: cn('vega-actions bg-background pointer-
|
|
21
|
+
return (_jsx("div", { className: cn('vega-actions bg-background pointer-events-none absolute top-1 right-0 z-10 flex items-center gap-1 opacity-0 transition-opacity peer-focus-within:pointer-events-auto peer-focus-within:opacity-100 peer-hover:pointer-events-auto peer-hover:opacity-100 focus-within:pointer-events-auto focus-within:opacity-100 hover:pointer-events-auto hover:opacity-100 pointer-coarse:pointer-events-auto pointer-coarse:opacity-100', className), children: children }));
|
|
22
22
|
};
|
|
23
23
|
//# sourceMappingURL=VegaChartActions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaChartActions.js","sourceRoot":"","sources":["../src/VegaChartActions.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAchC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAoC,CAAC,EAChE,QAAQ,EACR,SAAS,GACV,EAAE,EAAE;IACH,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CACX,+ZAA+Z,EAC/Z,SAAS,CACV,YAEA,QAAQ,GACL,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {cn} from '@sqlrooms/ui';\nimport React from 'react';\n\nexport interface VegaChartActionsProps {\n /**\n * Action components to render in the toolbar\n */\n children: React.ReactNode;\n /**\n * Additional CSS classes for the container\n */\n className?: string;\n}\n\n/**\n * Container component for chart actions toolbar.\n * Positions actions as an overlay in the top-right corner of the chart.\n *\n * @example\n * ```tsx\n * <VegaLiteArrowChart spec={spec} arrowTable={data}>\n * <VegaChartActions>\n * <VegaExportAction />\n * <Separator orientation=\"vertical\" className=\"h-4\" />\n * <Button size=\"xs\" variant=\"ghost\" onClick={handleRefresh}>\n * <RefreshCw className=\"h-4 w-4\" />\n * </Button>\n * </VegaChartActions>\n * </VegaLiteArrowChart>\n * ```\n */\nexport const VegaChartActions: React.FC<VegaChartActionsProps> = ({\n children,\n className,\n}) => {\n return (\n <div\n className={cn(\n 'vega-actions bg-background pointer-
|
|
1
|
+
{"version":3,"file":"VegaChartActions.js","sourceRoot":"","sources":["../src/VegaChartActions.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAchC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAoC,CAAC,EAChE,QAAQ,EACR,SAAS,GACV,EAAE,EAAE;IACH,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CACX,+ZAA+Z,EAC/Z,SAAS,CACV,YAEA,QAAQ,GACL,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {cn} from '@sqlrooms/ui';\nimport React from 'react';\n\nexport interface VegaChartActionsProps {\n /**\n * Action components to render in the toolbar\n */\n children: React.ReactNode;\n /**\n * Additional CSS classes for the container\n */\n className?: string;\n}\n\n/**\n * Container component for chart actions toolbar.\n * Positions actions as an overlay in the top-right corner of the chart.\n *\n * @example\n * ```tsx\n * <VegaLiteArrowChart spec={spec} arrowTable={data}>\n * <VegaChartActions>\n * <VegaExportAction />\n * <Separator orientation=\"vertical\" className=\"h-4\" />\n * <Button size=\"xs\" variant=\"ghost\" onClick={handleRefresh}>\n * <RefreshCw className=\"h-4 w-4\" />\n * </Button>\n * </VegaChartActions>\n * </VegaLiteArrowChart>\n * ```\n */\nexport const VegaChartActions: React.FC<VegaChartActionsProps> = ({\n children,\n className,\n}) => {\n return (\n <div\n className={cn(\n 'vega-actions bg-background pointer-events-none absolute top-1 right-0 z-10 flex items-center gap-1 opacity-0 transition-opacity peer-focus-within:pointer-events-auto peer-focus-within:opacity-100 peer-hover:pointer-events-auto peer-hover:opacity-100 focus-within:pointer-events-auto focus-within:opacity-100 hover:pointer-events-auto hover:opacity-100 pointer-coarse:pointer-events-auto pointer-coarse:opacity-100',\n className,\n )}\n >\n {children}\n </div>\n );\n};\n"]}
|
package/dist/VegaChartTool.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import { TopLevelSpec } from 'vega-lite';
|
|
3
|
+
import type { DuckDbConnector } from '@sqlrooms/duckdb';
|
|
4
|
+
/**
|
|
5
|
+
* Creates a SQL validator that checks queries by executing `SELECT 1 FROM (<query>) LIMIT 1`.
|
|
6
|
+
* Returns an error message if the query fails or produces no rows.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createSqlValidator(getConnector: () => DuckDbConnector | Promise<DuckDbConnector>): NonNullable<VegaChartToolOptions['validateSql']>;
|
|
5
9
|
/**
|
|
6
10
|
* Zod schema for the VegaChart tool parameters
|
|
7
11
|
*/
|
|
@@ -11,20 +15,13 @@ export declare const VegaChartToolParameters: z.ZodObject<{
|
|
|
11
15
|
reasoning: z.ZodString;
|
|
12
16
|
}, z.core.$strip>;
|
|
13
17
|
export type VegaChartToolParameters = z.infer<typeof VegaChartToolParameters>;
|
|
14
|
-
export type
|
|
15
|
-
sqlQuery: z.ZodString;
|
|
16
|
-
vegaLiteSpec: z.ZodString;
|
|
17
|
-
reasoning: z.ZodString;
|
|
18
|
-
}>;
|
|
19
|
-
export type VegaChartToolLlmResult = {
|
|
18
|
+
export type VegaChartToolOutput = {
|
|
20
19
|
success: boolean;
|
|
21
20
|
details: string;
|
|
22
|
-
};
|
|
23
|
-
export type VegaChartToolAdditionalData = {
|
|
24
21
|
sqlQuery: string;
|
|
25
|
-
vegaLiteSpec:
|
|
22
|
+
vegaLiteSpec: TopLevelSpec | null;
|
|
23
|
+
error?: string;
|
|
26
24
|
};
|
|
27
|
-
export type VegaChartToolContext = unknown;
|
|
28
25
|
/**
|
|
29
26
|
* Default description for the VegaChart tool
|
|
30
27
|
*/
|
|
@@ -38,19 +35,21 @@ export type VegaChartToolOptions = {
|
|
|
38
35
|
*/
|
|
39
36
|
description?: string;
|
|
40
37
|
/**
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Which editors to show when editing
|
|
51
|
-
* @default 'both'
|
|
38
|
+
* Optional callback to validate the SQL query before rendering the chart.
|
|
39
|
+
* When provided, the tool will execute this function to catch SQL errors
|
|
40
|
+
* or empty results early, so the LLM can fix the query and retry.
|
|
41
|
+
*
|
|
42
|
+
* The function receives the SQL query string and an optional AbortSignal,
|
|
43
|
+
* and should return `{valid: true}` or `{valid: false, error: string}`.
|
|
44
|
+
*
|
|
45
|
+
* For performance, implementations should use `LIMIT 1` or equivalent.
|
|
52
46
|
*/
|
|
53
|
-
|
|
47
|
+
validateSql?: (sqlQuery: string, abortSignal?: AbortSignal) => Promise<{
|
|
48
|
+
valid: true;
|
|
49
|
+
} | {
|
|
50
|
+
valid: false;
|
|
51
|
+
error: string;
|
|
52
|
+
}>;
|
|
54
53
|
};
|
|
55
54
|
/**
|
|
56
55
|
* Creates a VegaLite chart visualization tool for AI assistants
|
|
@@ -60,5 +59,27 @@ export type VegaChartToolOptions = {
|
|
|
60
59
|
* @param options.editorMode - Which editors to show ('spec', 'sql', 'both', 'none')
|
|
61
60
|
* @returns A tool that can be used with the AI assistant
|
|
62
61
|
*/
|
|
63
|
-
export declare function createVegaChartTool({ description,
|
|
62
|
+
export declare function createVegaChartTool({ description, validateSql, }?: VegaChartToolOptions): import("ai").Tool<{
|
|
63
|
+
sqlQuery: string;
|
|
64
|
+
vegaLiteSpec: string;
|
|
65
|
+
reasoning: string;
|
|
66
|
+
}, {
|
|
67
|
+
success: boolean;
|
|
68
|
+
details: string;
|
|
69
|
+
sqlQuery: string;
|
|
70
|
+
vegaLiteSpec: null;
|
|
71
|
+
error?: undefined;
|
|
72
|
+
} | {
|
|
73
|
+
success: boolean;
|
|
74
|
+
details: string;
|
|
75
|
+
sqlQuery: string;
|
|
76
|
+
vegaLiteSpec: TopLevelSpec;
|
|
77
|
+
error?: undefined;
|
|
78
|
+
} | {
|
|
79
|
+
success: boolean;
|
|
80
|
+
details: string;
|
|
81
|
+
error: string;
|
|
82
|
+
sqlQuery: string;
|
|
83
|
+
vegaLiteSpec: null;
|
|
84
|
+
}>;
|
|
64
85
|
//# sourceMappingURL=VegaChartTool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaChartTool.d.ts","sourceRoot":"","sources":["../src/VegaChartTool.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VegaChartTool.d.ts","sourceRoot":"","sources":["../src/VegaChartTool.tsx"],"names":[],"mappings":"AACA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,EAAU,YAAY,EAAC,MAAM,WAAW,CAAC;AAEhD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAEtD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,GAC7D,WAAW,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAC,CAmBlD;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;iBAIlC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE9E,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,8BAA8B,smCAY4I,CAAC;AAExL;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,CACZ,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,WAAW,KACtB,OAAO,CAAC;QAAC,KAAK,EAAE,IAAI,CAAA;KAAC,GAAG;QAAC,KAAK,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;CAC7D,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,WAA4C,EAC5C,WAAW,GACZ,GAAE,oBAAyB;;;;;;;;;;;;;;;;;;;;;;GAqE3B"}
|