Skip to content

Commit 4a15c1b

Browse files
committed
Handle invalid vega charts
1 parent b9b1283 commit 4a15c1b

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

ui/src/pages/chat/utils/toolExecutors.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ export interface ToolExecutorContext {
6161
onStatusMessage?: (toolCallId: string, message: string) => void;
6262
/** Default model for sub-agent tool when no model is specified in arguments */
6363
defaultModel?: string;
64-
/** Conversation ID for per-conversation MCP sessions */
65-
conversationId?: string;
6664
}
6765

6866
/**
@@ -1717,8 +1715,9 @@ interface ChartRenderArguments {
17171715
/**
17181716
* Execute the chart_render tool
17191717
*
1720-
* Takes a Vega-Lite specification and returns it as a chart artifact for rendering.
1721-
* The chart is rendered client-side using vega-embed.
1718+
* Takes a Vega-Lite specification, validates it by compiling, and returns it as
1719+
* a chart artifact for rendering. If the spec is invalid, returns an error so
1720+
* the model can retry with a corrected spec.
17221721
*/
17231722
export const chartRenderExecutor: ToolExecutor = async (
17241723
toolCall,
@@ -1742,6 +1741,20 @@ export const chartRenderExecutor: ToolExecutor = async (
17421741
};
17431742
}
17441743

1744+
// Validate the spec by compiling it with vega-lite before reporting success.
1745+
// This catches invalid specs early so the model can retry.
1746+
try {
1747+
const { compile } = await import("vega-lite");
1748+
compile(spec as unknown as Parameters<typeof compile>[0]);
1749+
} catch (err) {
1750+
const message = err instanceof Error ? err.message : String(err);
1751+
return {
1752+
success: false,
1753+
error: message,
1754+
output: JSON.stringify({ error: `Invalid Vega-Lite spec: ${message}` }),
1755+
};
1756+
}
1757+
17451758
// Generate a unique ID for the artifact
17461759
const toolId = toolCall.id || `chart-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
17471760

@@ -2425,7 +2438,7 @@ const mcpToolExecutor: ToolExecutor = async (toolCall, context) => {
24252438
}
24262439

24272440
try {
2428-
const result = await callMCPTool(serverId, toolName, args, context.conversationId);
2441+
const result = await callMCPTool(serverId, toolName, args);
24292442

24302443
// Clear status message
24312444
context.onStatusMessage?.(toolCall.id, "");

0 commit comments

Comments
 (0)