@@ -7,7 +7,11 @@ import { TabsContent } from "@/components/ui/tabs";
77import { Textarea } from "@/components/ui/textarea" ;
88import DynamicJsonForm from "./DynamicJsonForm" ;
99import type { JsonValue , JsonSchemaType } from "@/utils/jsonUtils" ;
10- import { generateDefaultValue , validateToolOutput , hasOutputSchema } from "@/utils/schemaUtils" ;
10+ import {
11+ generateDefaultValue ,
12+ validateToolOutput ,
13+ hasOutputSchema ,
14+ } from "@/utils/schemaUtils" ;
1115import {
1216 CallToolResultSchema ,
1317 CompatibilityCallToolResult ,
@@ -56,46 +60,54 @@ const ToolsTab = ({
5660 // Check compatibility between structured and unstructured content
5761 const checkContentCompatibility = (
5862 structuredContent : unknown ,
59- unstructuredContent : Array < { type : string ; text ?: string ; [ key : string ] : unknown } >
63+ unstructuredContent : Array < {
64+ type : string ;
65+ text ?: string ;
66+ [ key : string ] : unknown ;
67+ } > ,
6068 ) : { isCompatible : boolean ; message : string } => {
6169 // Check if unstructured content is a single text block
62- if ( unstructuredContent . length !== 1 || unstructuredContent [ 0 ] . type !== "text" ) {
70+ if (
71+ unstructuredContent . length !== 1 ||
72+ unstructuredContent [ 0 ] . type !== "text"
73+ ) {
6374 return {
6475 isCompatible : false ,
65- message : "Unstructured content is not a single text block"
76+ message : "Unstructured content is not a single text block" ,
6677 } ;
6778 }
6879
6980 const textContent = unstructuredContent [ 0 ] . text ;
7081 if ( ! textContent ) {
7182 return {
7283 isCompatible : false ,
73- message : "Text content is empty"
84+ message : "Text content is empty" ,
7485 } ;
7586 }
7687
7788 try {
7889 // Try to parse the text as JSON
7990 const parsedContent = JSON . parse ( textContent ) ;
80-
91+
8192 // Deep equality check
82- const isEqual = JSON . stringify ( parsedContent ) === JSON . stringify ( structuredContent ) ;
83-
93+ const isEqual =
94+ JSON . stringify ( parsedContent ) === JSON . stringify ( structuredContent ) ;
95+
8496 if ( isEqual ) {
8597 return {
8698 isCompatible : true ,
87- message : "Unstructured content matches structured content"
99+ message : "Unstructured content matches structured content" ,
88100 } ;
89101 } else {
90102 return {
91103 isCompatible : false ,
92- message : "Parsed JSON does not match structured content"
104+ message : "Parsed JSON does not match structured content" ,
93105 } ;
94106 }
95107 } catch ( e ) {
96108 return {
97109 isCompatible : false ,
98- message : "Unstructured content is not valid JSON"
110+ message : "Unstructured content is not valid JSON" ,
99111 } ;
100112 }
101113 } ;
@@ -122,31 +134,38 @@ const ToolsTab = ({
122134
123135 // Validate structured content if present and tool has output schema
124136 let validationResult = null ;
125- const toolHasOutputSchema = selectedTool && hasOutputSchema ( selectedTool . name ) ;
126-
137+ const toolHasOutputSchema =
138+ selectedTool && hasOutputSchema ( selectedTool . name ) ;
139+
127140 if ( toolHasOutputSchema ) {
128141 if ( ! structuredResult . structuredContent && ! isError ) {
129142 // Tool has output schema but didn't return structured content (and it's not an error)
130143 validationResult = {
131144 isValid : false ,
132- error : "Tool has an output schema but did not return structured content"
145+ error :
146+ "Tool has an output schema but did not return structured content" ,
133147 } ;
134148 } else if ( structuredResult . structuredContent ) {
135149 // Validate the structured content
136- validationResult = validateToolOutput ( selectedTool . name , structuredResult . structuredContent ) ;
150+ validationResult = validateToolOutput (
151+ selectedTool . name ,
152+ structuredResult . structuredContent ,
153+ ) ;
137154 }
138155 }
139156
140157 // Check compatibility if both structured and unstructured content exist
141158 // AND the tool has an output schema
142159 let compatibilityResult = null ;
143- if ( structuredResult . structuredContent &&
144- structuredResult . content . length > 0 &&
145- selectedTool &&
146- hasOutputSchema ( selectedTool . name ) ) {
160+ if (
161+ structuredResult . structuredContent &&
162+ structuredResult . content . length > 0 &&
163+ selectedTool &&
164+ hasOutputSchema ( selectedTool . name )
165+ ) {
147166 compatibilityResult = checkContentCompatibility (
148167 structuredResult . structuredContent ,
149- structuredResult . content
168+ structuredResult . content ,
150169 ) ;
151170 }
152171
@@ -162,46 +181,55 @@ const ToolsTab = ({
162181 </ h4 >
163182 { structuredResult . structuredContent && (
164183 < div className = "mb-4" >
165- < h5 className = "font-semibold mb-2 text-sm" > Structured Content:</ h5 >
184+ < h5 className = "font-semibold mb-2 text-sm" >
185+ Structured Content:
186+ </ h5 >
166187 < div className = "bg-gray-50 dark:bg-gray-900 p-3 rounded-lg" >
167188 < JsonView data = { structuredResult . structuredContent } />
168189 { validationResult && (
169- < div className = { `mt-2 p-2 rounded text-sm ${
170- validationResult . isValid
171- ? "bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200"
172- : "bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200"
173- } `} >
190+ < div
191+ className = { `mt-2 p-2 rounded text-sm ${
192+ validationResult . isValid
193+ ? "bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200"
194+ : "bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200"
195+ } `}
196+ >
174197 { validationResult . isValid ? (
175198 "✓ Valid according to output schema"
176199 ) : (
177- < >
178- ✗ Validation Error: { validationResult . error }
179- </ >
200+ < > ✗ Validation Error: { validationResult . error } </ >
180201 ) }
181202 </ div >
182203 ) }
183204 </ div >
184205 </ div >
185206 ) }
186- { ! structuredResult . structuredContent && validationResult && ! validationResult . isValid && (
187- < div className = "mb-4" >
188- < div className = "bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200 p-2 rounded text-sm" >
189- ✗ Validation Error: { validationResult . error }
207+ { ! structuredResult . structuredContent &&
208+ validationResult &&
209+ ! validationResult . isValid && (
210+ < div className = "mb-4" >
211+ < div className = "bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200 p-2 rounded text-sm" >
212+ ✗ Validation Error: { validationResult . error }
213+ </ div >
190214 </ div >
191- </ div >
192- ) }
215+ ) }
193216 { structuredResult . content . length > 0 && (
194217 < div className = "mb-4" >
195218 { structuredResult . structuredContent && (
196219 < >
197- < h5 className = "font-semibold mb-2 text-sm" > Unstructured Content:</ h5 >
220+ < h5 className = "font-semibold mb-2 text-sm" >
221+ Unstructured Content:
222+ </ h5 >
198223 { compatibilityResult && (
199- < div className = { `mb-2 p-2 rounded text-sm ${
200- compatibilityResult . isCompatible
201- ? "bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200"
202- : "bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200"
203- } `} >
204- { compatibilityResult . isCompatible ? "✓" : "⚠" } { compatibilityResult . message }
224+ < div
225+ className = { `mb-2 p-2 rounded text-sm ${
226+ compatibilityResult . isCompatible
227+ ? "bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200"
228+ : "bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200"
229+ } `}
230+ >
231+ { compatibilityResult . isCompatible ? "✓" : "⚠" } { " " }
232+ { compatibilityResult . message }
205233 </ div >
206234 ) }
207235 </ >
@@ -211,25 +239,25 @@ const ToolsTab = ({
211239 { item . type === "text" && (
212240 < JsonView data = { item . text } isError = { isError } />
213241 ) }
214- { item . type === "image" && (
215- < img
216- src = { `data:${ item . mimeType } ;base64,${ item . data } ` }
217- alt = "Tool result image"
218- className = "max-w-full h-auto"
219- />
220- ) }
221- { item . type === "resource" &&
222- ( item . resource ?. mimeType ?. startsWith ( "audio/" ) ? (
223- < audio
224- controls
225- src = { `data:${ item . resource . mimeType } ;base64,${ item . resource . blob } ` }
226- className = "w-full"
227- >
228- < p > Your browser does not support audio playback</ p >
229- </ audio >
230- ) : (
231- < JsonView data = { item . resource } />
232- ) ) }
242+ { item . type === "image" && (
243+ < img
244+ src = { `data:${ item . mimeType } ;base64,${ item . data } ` }
245+ alt = "Tool result image"
246+ className = "max-w-full h-auto"
247+ />
248+ ) }
249+ { item . type === "resource" &&
250+ ( item . resource ?. mimeType ?. startsWith ( "audio/" ) ? (
251+ < audio
252+ controls
253+ src = { `data:${ item . resource . mimeType } ;base64,${ item . resource . blob } ` }
254+ className = "w-full"
255+ >
256+ < p > Your browser does not support audio playback</ p >
257+ </ audio >
258+ ) : (
259+ < JsonView data = { item . resource } />
260+ ) ) }
233261 </ div >
234262 ) ) }
235263 </ div >
@@ -395,7 +423,9 @@ const ToolsTab = ({
395423 < Button
396424 size = "sm"
397425 variant = "ghost"
398- onClick = { ( ) => setIsOutputSchemaExpanded ( ! isOutputSchemaExpanded ) }
426+ onClick = { ( ) =>
427+ setIsOutputSchemaExpanded ( ! isOutputSchemaExpanded )
428+ }
399429 className = "h-6 px-2"
400430 >
401431 { isOutputSchemaExpanded ? (
@@ -411,9 +441,13 @@ const ToolsTab = ({
411441 ) }
412442 </ Button >
413443 </ div >
414- < div className = { `transition-all ${
415- isOutputSchemaExpanded ? "" : "max-h-[8rem] overflow-y-auto"
416- } `} >
444+ < div
445+ className = { `transition-all ${
446+ isOutputSchemaExpanded
447+ ? ""
448+ : "max-h-[8rem] overflow-y-auto"
449+ } `}
450+ >
417451 < JsonView data = { selectedTool . outputSchema } />
418452 </ div >
419453 </ div >
0 commit comments