diff --git a/client/src/components/ToolsTab.tsx b/client/src/components/ToolsTab.tsx index 4f4e235f..ecadc8b9 100644 --- a/client/src/components/ToolsTab.tsx +++ b/client/src/components/ToolsTab.tsx @@ -7,7 +7,11 @@ import { TabsContent } from "@/components/ui/tabs"; import { Textarea } from "@/components/ui/textarea"; import DynamicJsonForm from "./DynamicJsonForm"; import type { JsonValue, JsonSchemaType } from "@/utils/jsonUtils"; -import { generateDefaultValue, validateToolOutput, hasOutputSchema } from "@/utils/schemaUtils"; +import { + generateDefaultValue, + validateToolOutput, + hasOutputSchema, +} from "@/utils/schemaUtils"; import { CallToolResultSchema, CompatibilityCallToolResult, @@ -56,13 +60,20 @@ const ToolsTab = ({ // Check compatibility between structured and unstructured content const checkContentCompatibility = ( structuredContent: unknown, - unstructuredContent: Array<{ type: string; text?: string; [key: string]: unknown }> + unstructuredContent: Array<{ + type: string; + text?: string; + [key: string]: unknown; + }>, ): { isCompatible: boolean; message: string } => { // Check if unstructured content is a single text block - if (unstructuredContent.length !== 1 || unstructuredContent[0].type !== "text") { + if ( + unstructuredContent.length !== 1 || + unstructuredContent[0].type !== "text" + ) { return { isCompatible: false, - message: "Unstructured content is not a single text block" + message: "Unstructured content is not a single text block", }; } @@ -70,32 +81,33 @@ const ToolsTab = ({ if (!textContent) { return { isCompatible: false, - message: "Text content is empty" + message: "Text content is empty", }; } try { // Try to parse the text as JSON const parsedContent = JSON.parse(textContent); - + // Deep equality check - const isEqual = JSON.stringify(parsedContent) === JSON.stringify(structuredContent); - + const isEqual = + JSON.stringify(parsedContent) === JSON.stringify(structuredContent); + if (isEqual) { return { isCompatible: true, - message: "Unstructured content matches structured content" + message: "Unstructured content matches structured content", }; } else { return { isCompatible: false, - message: "Parsed JSON does not match structured content" + message: "Parsed JSON does not match structured content", }; } } catch (e) { return { isCompatible: false, - message: "Unstructured content is not valid JSON" + message: "Unstructured content is not valid JSON", }; } }; @@ -122,31 +134,38 @@ const ToolsTab = ({ // Validate structured content if present and tool has output schema let validationResult = null; - const toolHasOutputSchema = selectedTool && hasOutputSchema(selectedTool.name); - + const toolHasOutputSchema = + selectedTool && hasOutputSchema(selectedTool.name); + if (toolHasOutputSchema) { if (!structuredResult.structuredContent && !isError) { // Tool has output schema but didn't return structured content (and it's not an error) validationResult = { isValid: false, - error: "Tool has an output schema but did not return structured content" + error: + "Tool has an output schema but did not return structured content", }; } else if (structuredResult.structuredContent) { // Validate the structured content - validationResult = validateToolOutput(selectedTool.name, structuredResult.structuredContent); + validationResult = validateToolOutput( + selectedTool.name, + structuredResult.structuredContent, + ); } } // Check compatibility if both structured and unstructured content exist // AND the tool has an output schema let compatibilityResult = null; - if (structuredResult.structuredContent && - structuredResult.content.length > 0 && - selectedTool && - hasOutputSchema(selectedTool.name)) { + if ( + structuredResult.structuredContent && + structuredResult.content.length > 0 && + selectedTool && + hasOutputSchema(selectedTool.name) + ) { compatibilityResult = checkContentCompatibility( structuredResult.structuredContent, - structuredResult.content + structuredResult.content, ); } @@ -162,46 +181,55 @@ const ToolsTab = ({ {structuredResult.structuredContent && (