style: Apply Prettier formatting to structured output code

Applied consistent formatting to ToolsTab.tsx and schemaUtils.ts
to fix linting issues. No functional changes.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Basil Hosmer 2025-05-27 18:14:15 -04:00
commit b184654ee5
No known key found for this signature in database
2 changed files with 107 additions and 68 deletions

View file

@ -7,7 +7,11 @@ import { TabsContent } from "@/components/ui/tabs";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import DynamicJsonForm from "./DynamicJsonForm"; import DynamicJsonForm from "./DynamicJsonForm";
import type { JsonValue, JsonSchemaType } from "@/utils/jsonUtils"; import type { JsonValue, JsonSchemaType } from "@/utils/jsonUtils";
import { generateDefaultValue, validateToolOutput, hasOutputSchema } from "@/utils/schemaUtils"; import {
generateDefaultValue,
validateToolOutput,
hasOutputSchema,
} from "@/utils/schemaUtils";
import { import {
CallToolResultSchema, CallToolResultSchema,
CompatibilityCallToolResult, CompatibilityCallToolResult,
@ -56,13 +60,20 @@ const ToolsTab = ({
// Check compatibility between structured and unstructured content // Check compatibility between structured and unstructured content
const checkContentCompatibility = ( const checkContentCompatibility = (
structuredContent: unknown, structuredContent: unknown,
unstructuredContent: Array<{ type: string; text?: string; [key: string]: unknown }> unstructuredContent: Array<{
type: string;
text?: string;
[key: string]: unknown;
}>,
): { isCompatible: boolean; message: string } => { ): { isCompatible: boolean; message: string } => {
// Check if unstructured content is a single text block // 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 { return {
isCompatible: false, 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) { if (!textContent) {
return { return {
isCompatible: false, isCompatible: false,
message: "Text content is empty" message: "Text content is empty",
}; };
} }
try { try {
// Try to parse the text as JSON // Try to parse the text as JSON
const parsedContent = JSON.parse(textContent); const parsedContent = JSON.parse(textContent);
// Deep equality check // Deep equality check
const isEqual = JSON.stringify(parsedContent) === JSON.stringify(structuredContent); const isEqual =
JSON.stringify(parsedContent) === JSON.stringify(structuredContent);
if (isEqual) { if (isEqual) {
return { return {
isCompatible: true, isCompatible: true,
message: "Unstructured content matches structured content" message: "Unstructured content matches structured content",
}; };
} else { } else {
return { return {
isCompatible: false, isCompatible: false,
message: "Parsed JSON does not match structured content" message: "Parsed JSON does not match structured content",
}; };
} }
} catch (e) { } catch (e) {
return { return {
isCompatible: false, 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 // Validate structured content if present and tool has output schema
let validationResult = null; let validationResult = null;
const toolHasOutputSchema = selectedTool && hasOutputSchema(selectedTool.name); const toolHasOutputSchema =
selectedTool && hasOutputSchema(selectedTool.name);
if (toolHasOutputSchema) { if (toolHasOutputSchema) {
if (!structuredResult.structuredContent && !isError) { if (!structuredResult.structuredContent && !isError) {
// Tool has output schema but didn't return structured content (and it's not an error) // Tool has output schema but didn't return structured content (and it's not an error)
validationResult = { validationResult = {
isValid: false, 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) { } else if (structuredResult.structuredContent) {
// Validate the structured content // 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 // Check compatibility if both structured and unstructured content exist
// AND the tool has an output schema // AND the tool has an output schema
let compatibilityResult = null; let compatibilityResult = null;
if (structuredResult.structuredContent && if (
structuredResult.content.length > 0 && structuredResult.structuredContent &&
selectedTool && structuredResult.content.length > 0 &&
hasOutputSchema(selectedTool.name)) { selectedTool &&
hasOutputSchema(selectedTool.name)
) {
compatibilityResult = checkContentCompatibility( compatibilityResult = checkContentCompatibility(
structuredResult.structuredContent, structuredResult.structuredContent,
structuredResult.content structuredResult.content,
); );
} }
@ -162,46 +181,55 @@ const ToolsTab = ({
</h4> </h4>
{structuredResult.structuredContent && ( {structuredResult.structuredContent && (
<div className="mb-4"> <div className="mb-4">
<h5 className="font-semibold mb-2 text-sm">Structured Content:</h5> <h5 className="font-semibold mb-2 text-sm">
Structured Content:
</h5>
<div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg"> <div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg">
<JsonView data={structuredResult.structuredContent} /> <JsonView data={structuredResult.structuredContent} />
{validationResult && ( {validationResult && (
<div className={`mt-2 p-2 rounded text-sm ${ <div
validationResult.isValid className={`mt-2 p-2 rounded text-sm ${
? "bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200" validationResult.isValid
: "bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200" ? "bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200"
}`}> : "bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200"
}`}
>
{validationResult.isValid ? ( {validationResult.isValid ? (
"✓ Valid according to output schema" "✓ Valid according to output schema"
) : ( ) : (
<> <>✗ Validation Error: {validationResult.error}</>
✗ Validation Error: {validationResult.error}
</>
)} )}
</div> </div>
)} )}
</div> </div>
</div> </div>
)} )}
{!structuredResult.structuredContent && validationResult && !validationResult.isValid && ( {!structuredResult.structuredContent &&
<div className="mb-4"> validationResult &&
<div className="bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200 p-2 rounded text-sm"> !validationResult.isValid && (
✗ Validation Error: {validationResult.error} <div className="mb-4">
<div className="bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200 p-2 rounded text-sm">
✗ Validation Error: {validationResult.error}
</div>
</div> </div>
</div> )}
)}
{structuredResult.content.length > 0 && ( {structuredResult.content.length > 0 && (
<div className="mb-4"> <div className="mb-4">
{structuredResult.structuredContent && ( {structuredResult.structuredContent && (
<> <>
<h5 className="font-semibold mb-2 text-sm">Unstructured Content:</h5> <h5 className="font-semibold mb-2 text-sm">
Unstructured Content:
</h5>
{compatibilityResult && ( {compatibilityResult && (
<div className={`mb-2 p-2 rounded text-sm ${ <div
compatibilityResult.isCompatible className={`mb-2 p-2 rounded text-sm ${
? "bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200" compatibilityResult.isCompatible
: "bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200" ? "bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200"
}`}> : "bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200"
{compatibilityResult.isCompatible ? "✓" : "⚠"} {compatibilityResult.message} }`}
>
{compatibilityResult.isCompatible ? "✓" : "⚠"}{" "}
{compatibilityResult.message}
</div> </div>
)} )}
</> </>
@ -211,25 +239,25 @@ const ToolsTab = ({
{item.type === "text" && ( {item.type === "text" && (
<JsonView data={item.text} isError={isError} /> <JsonView data={item.text} isError={isError} />
)} )}
{item.type === "image" && ( {item.type === "image" && (
<img <img
src={`data:${item.mimeType};base64,${item.data}`} src={`data:${item.mimeType};base64,${item.data}`}
alt="Tool result image" alt="Tool result image"
className="max-w-full h-auto" className="max-w-full h-auto"
/> />
)} )}
{item.type === "resource" && {item.type === "resource" &&
(item.resource?.mimeType?.startsWith("audio/") ? ( (item.resource?.mimeType?.startsWith("audio/") ? (
<audio <audio
controls controls
src={`data:${item.resource.mimeType};base64,${item.resource.blob}`} src={`data:${item.resource.mimeType};base64,${item.resource.blob}`}
className="w-full" className="w-full"
> >
<p>Your browser does not support audio playback</p> <p>Your browser does not support audio playback</p>
</audio> </audio>
) : ( ) : (
<JsonView data={item.resource} /> <JsonView data={item.resource} />
))} ))}
</div> </div>
))} ))}
</div> </div>
@ -395,7 +423,9 @@ const ToolsTab = ({
<Button <Button
size="sm" size="sm"
variant="ghost" variant="ghost"
onClick={() => setIsOutputSchemaExpanded(!isOutputSchemaExpanded)} onClick={() =>
setIsOutputSchemaExpanded(!isOutputSchemaExpanded)
}
className="h-6 px-2" className="h-6 px-2"
> >
{isOutputSchemaExpanded ? ( {isOutputSchemaExpanded ? (
@ -411,9 +441,13 @@ const ToolsTab = ({
)} )}
</Button> </Button>
</div> </div>
<div className={`transition-all ${ <div
isOutputSchemaExpanded ? "" : "max-h-[8rem] overflow-y-auto" className={`transition-all ${
}`}> isOutputSchemaExpanded
? ""
: "max-h-[8rem] overflow-y-auto"
}`}
>
<JsonView data={selectedTool.outputSchema} /> <JsonView data={selectedTool.outputSchema} />
</div> </div>
</div> </div>

View file

@ -22,7 +22,10 @@ export function cacheToolOutputSchemas(tools: Tool[]): void {
const validator = ajv.compile(tool.outputSchema); const validator = ajv.compile(tool.outputSchema);
toolOutputValidators.set(tool.name, validator); toolOutputValidators.set(tool.name, validator);
} catch (error) { } catch (error) {
console.warn(`Failed to compile output schema for tool ${tool.name}:`, error); console.warn(
`Failed to compile output schema for tool ${tool.name}:`,
error,
);
} }
} }
} }
@ -34,7 +37,9 @@ export function cacheToolOutputSchemas(tools: Tool[]): void {
* @param toolName Name of the tool * @param toolName Name of the tool
* @returns The compiled validator function, or undefined if not found * @returns The compiled validator function, or undefined if not found
*/ */
export function getToolOutputValidator(toolName: string): ValidateFunction | undefined { export function getToolOutputValidator(
toolName: string,
): ValidateFunction | undefined {
return toolOutputValidators.get(toolName); return toolOutputValidators.get(toolName);
} }
@ -47,7 +52,7 @@ export function getToolOutputValidator(toolName: string): ValidateFunction | und
*/ */
export function validateToolOutput( export function validateToolOutput(
toolName: string, toolName: string,
structuredContent: unknown structuredContent: unknown,
): { isValid: boolean; error?: string } { ): { isValid: boolean; error?: string } {
const validator = getToolOutputValidator(toolName); const validator = getToolOutputValidator(toolName);
if (!validator) { if (!validator) {