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:
parent
cf1fb61de4
commit
b184654ee5
2 changed files with 107 additions and 68 deletions
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue