@@ -160,184 +160,214 @@ const ToolsTab = ({
160
160
const required = isPropertyRequired ( key , inputSchema ) ;
161
161
return (
162
162
< div key = { key } >
163
- < Label
164
- htmlFor = { key }
165
- className = "block text-sm font-medium text-gray-700 dark:text-gray-300"
166
- >
167
- { key }
168
- { required && (
169
- < span className = "text-red-500 ml-1" > *</ span >
170
- ) }
171
- </ Label >
172
- { prop . type === "boolean" ? (
173
- < div className = "flex items-center space-x-2 mt-2" >
174
- < Checkbox
175
- id = { key }
176
- name = { key }
177
- checked = { ! ! params [ key ] }
178
- onCheckedChange = { ( checked : boolean ) =>
179
- setParams ( {
180
- ...params ,
181
- [ key ] : checked ,
182
- } )
183
- }
184
- />
185
- < label
186
- htmlFor = { key }
187
- className = "text-sm font-medium text-gray-700 dark:text-gray-300"
188
- >
189
- { prop . description || "Toggle this option" }
190
- </ label >
191
- </ div >
192
- ) : prop . type === "string" && prop . enum ? (
193
- < Select
194
- value = {
195
- params [ key ] === undefined
196
- ? ""
197
- : String ( params [ key ] )
198
- }
199
- onValueChange = { ( value ) => {
200
- if ( value === "" ) {
201
- setParams ( {
202
- ...params ,
203
- [ key ] : undefined ,
204
- } ) ;
205
- } else {
206
- setParams ( {
207
- ...params ,
208
- [ key ] : value ,
209
- } ) ;
210
- }
211
- } }
163
+ < div className = "flex justify-between" >
164
+ < Label
165
+ htmlFor = { key }
166
+ className = "block text-sm font-medium text-gray-700 dark:text-gray-300"
212
167
>
213
- < SelectTrigger id = { key } className = "mt-1" >
214
- < SelectValue
215
- placeholder = {
216
- prop . description || "Select an option"
168
+ { key }
169
+ { required && (
170
+ < span className = "text-red-500 ml-1" > *</ span >
171
+ ) }
172
+ </ Label >
173
+ { prop . nullable ? (
174
+ < div className = "flex items-center space-x-2" >
175
+ < Checkbox
176
+ id = { key }
177
+ name = { key }
178
+ checked = { params [ key ] === null }
179
+ onCheckedChange = { ( checked : boolean ) =>
180
+ setParams ( {
181
+ ...params ,
182
+ [ key ] : checked ? null : prop . default ,
183
+ } )
184
+ }
185
+ />
186
+ < label
187
+ htmlFor = { key }
188
+ className = "text-sm font-medium text-gray-700 dark:text-gray-300"
189
+ >
190
+ null
191
+ </ label >
192
+ </ div >
193
+ ) : null }
194
+ </ div >
195
+
196
+ < div
197
+ role = "toolinputwrapper"
198
+ className = { `${ prop . nullable && params [ key ] === null ? "pointer-events-none opacity-50" : "" } ` }
199
+ >
200
+ { prop . type === "boolean" ? (
201
+ < div className = "flex items-center space-x-2 mt-2" >
202
+ < Checkbox
203
+ id = { key }
204
+ name = { key }
205
+ checked = { ! ! params [ key ] }
206
+ onCheckedChange = { ( checked : boolean ) =>
207
+ setParams ( {
208
+ ...params ,
209
+ [ key ] : checked ,
210
+ } )
217
211
}
218
212
/>
219
- </ SelectTrigger >
220
- < SelectContent >
221
- { prop . enum . map ( ( option ) => (
222
- < SelectItem key = { option } value = { option } >
223
- { option }
224
- </ SelectItem >
225
- ) ) }
226
- </ SelectContent >
227
- </ Select >
228
- ) : prop . type === "string" ? (
229
- < Textarea
230
- id = { key }
231
- name = { key }
232
- placeholder = { prop . description }
233
- value = {
234
- params [ key ] === undefined
235
- ? ""
236
- : String ( params [ key ] )
237
- }
238
- onChange = { ( e ) => {
239
- const value = e . target . value ;
240
- if ( value === "" ) {
241
- // Field cleared - set to undefined
242
- setParams ( {
243
- ...params ,
244
- [ key ] : undefined ,
245
- } ) ;
246
- } else {
247
- // Field has value - keep as string
248
- setParams ( {
249
- ...params ,
250
- [ key ] : value ,
251
- } ) ;
213
+ < label
214
+ htmlFor = { key }
215
+ className = "text-sm font-medium text-gray-700 dark:text-gray-300"
216
+ >
217
+ { prop . description || "Toggle this option" }
218
+ </ label >
219
+ </ div >
220
+ ) : prop . type === "string" && prop . enum ? (
221
+ < Select
222
+ value = {
223
+ params [ key ] === undefined
224
+ ? ""
225
+ : String ( params [ key ] )
252
226
}
253
- } }
254
- className = "mt-1"
255
- />
256
- ) : prop . type === "object" || prop . type === "array" ? (
257
- < div className = "mt-1" >
258
- < DynamicJsonForm
259
- ref = { ( ref ) => ( formRefs . current [ key ] = ref ) }
260
- schema = { {
261
- type : prop . type ,
262
- properties : prop . properties ,
263
- description : prop . description ,
264
- items : prop . items ,
227
+ onValueChange = { ( value ) => {
228
+ if ( value === "" ) {
229
+ setParams ( {
230
+ ... params ,
231
+ [ key ] : undefined ,
232
+ } ) ;
233
+ } else {
234
+ setParams ( {
235
+ ... params ,
236
+ [ key ] : value ,
237
+ } ) ;
238
+ }
265
239
} }
240
+ >
241
+ < SelectTrigger id = { key } className = "mt-1" >
242
+ < SelectValue
243
+ placeholder = {
244
+ prop . description || "Select an option"
245
+ }
246
+ />
247
+ </ SelectTrigger >
248
+ < SelectContent >
249
+ { prop . enum . map ( ( option ) => (
250
+ < SelectItem key = { option } value = { option } >
251
+ { option }
252
+ </ SelectItem >
253
+ ) ) }
254
+ </ SelectContent >
255
+ </ Select >
256
+ ) : prop . type === "string" ? (
257
+ < Textarea
258
+ id = { key }
259
+ name = { key }
260
+ placeholder = { prop . description }
266
261
value = {
267
- ( params [ key ] as JsonValue ) ??
268
- generateDefaultValue ( prop )
262
+ params [ key ] === undefined
263
+ ? ""
264
+ : String ( params [ key ] )
269
265
}
270
- onChange = { ( newValue : JsonValue ) => {
271
- setParams ( {
272
- ...params ,
273
- [ key ] : newValue ,
274
- } ) ;
275
- // Check validation after a short delay to allow form to update
276
- setTimeout ( checkValidationErrors , 100 ) ;
277
- } }
278
- />
279
- </ div >
280
- ) : prop . type === "number" ||
281
- prop . type === "integer" ? (
282
- < Input
283
- type = "number"
284
- id = { key }
285
- name = { key }
286
- placeholder = { prop . description }
287
- value = {
288
- params [ key ] === undefined
289
- ? ""
290
- : String ( params [ key ] )
291
- }
292
- onChange = { ( e ) => {
293
- const value = e . target . value ;
294
- if ( value === "" ) {
295
- // Field cleared - set to undefined
296
- setParams ( {
297
- ...params ,
298
- [ key ] : undefined ,
299
- } ) ;
300
- } else {
301
- // Field has value - try to convert to number, but store input either way
302
- const num = Number ( value ) ;
303
- if ( ! isNaN ( num ) ) {
266
+ onChange = { ( e ) => {
267
+ const value = e . target . value ;
268
+ if ( value === "" ) {
269
+ // Field cleared - set to undefined
304
270
setParams ( {
305
271
...params ,
306
- [ key ] : num ,
272
+ [ key ] : undefined ,
307
273
} ) ;
308
274
} else {
309
- // Store invalid input as string - let server validate
275
+ // Field has value - keep as string
310
276
setParams ( {
311
277
...params ,
312
278
[ key ] : value ,
313
279
} ) ;
314
280
}
315
- }
316
- } }
317
- className = "mt-1"
318
- />
319
- ) : (
320
- < div className = "mt-1" >
321
- < DynamicJsonForm
322
- ref = { ( ref ) => ( formRefs . current [ key ] = ref ) }
323
- schema = { {
324
- type : prop . type ,
325
- properties : prop . properties ,
326
- description : prop . description ,
327
- items : prop . items ,
328
281
} }
329
- value = { params [ key ] as JsonValue }
330
- onChange = { ( newValue : JsonValue ) => {
331
- setParams ( {
332
- ...params ,
333
- [ key ] : newValue ,
334
- } ) ;
335
- // Check validation after a short delay to allow form to update
336
- setTimeout ( checkValidationErrors , 100 ) ;
282
+ className = "mt-1"
283
+ />
284
+ ) : prop . type === "object" ||
285
+ prop . type === "array" ? (
286
+ < div className = "mt-1" >
287
+ < DynamicJsonForm
288
+ ref = { ( ref ) => ( formRefs . current [ key ] = ref ) }
289
+ schema = { {
290
+ type : prop . type ,
291
+ properties : prop . properties ,
292
+ description : prop . description ,
293
+ items : prop . items ,
294
+ } }
295
+ value = {
296
+ ( params [ key ] as JsonValue ) ??
297
+ generateDefaultValue ( prop )
298
+ }
299
+ onChange = { ( newValue : JsonValue ) => {
300
+ setParams ( {
301
+ ...params ,
302
+ [ key ] : newValue ,
303
+ } ) ;
304
+ // Check validation after a short delay to allow form to update
305
+ setTimeout ( checkValidationErrors , 100 ) ;
306
+ } }
307
+ />
308
+ </ div >
309
+ ) : prop . type === "number" ||
310
+ prop . type === "integer" ? (
311
+ < Input
312
+ type = "number"
313
+ id = { key }
314
+ name = { key }
315
+ placeholder = { prop . description }
316
+ value = {
317
+ params [ key ] === undefined
318
+ ? ""
319
+ : String ( params [ key ] )
320
+ }
321
+ onChange = { ( e ) => {
322
+ const value = e . target . value ;
323
+ if ( value === "" ) {
324
+ // Field cleared - set to undefined
325
+ setParams ( {
326
+ ...params ,
327
+ [ key ] : undefined ,
328
+ } ) ;
329
+ } else {
330
+ // Field has value - try to convert to number, but store input either way
331
+ const num = Number ( value ) ;
332
+ if ( ! isNaN ( num ) ) {
333
+ setParams ( {
334
+ ...params ,
335
+ [ key ] : num ,
336
+ } ) ;
337
+ } else {
338
+ // Store invalid input as string - let server validate
339
+ setParams ( {
340
+ ...params ,
341
+ [ key ] : value ,
342
+ } ) ;
343
+ }
344
+ }
337
345
} }
346
+ className = "mt-1"
338
347
/>
339
- </ div >
340
- ) }
348
+ ) : (
349
+ < div className = "mt-1" >
350
+ < DynamicJsonForm
351
+ ref = { ( ref ) => ( formRefs . current [ key ] = ref ) }
352
+ schema = { {
353
+ type : prop . type ,
354
+ properties : prop . properties ,
355
+ description : prop . description ,
356
+ items : prop . items ,
357
+ } }
358
+ value = { params [ key ] as JsonValue }
359
+ onChange = { ( newValue : JsonValue ) => {
360
+ setParams ( {
361
+ ...params ,
362
+ [ key ] : newValue ,
363
+ } ) ;
364
+ // Check validation after a short delay to allow form to update
365
+ setTimeout ( checkValidationErrors , 100 ) ;
366
+ } }
367
+ />
368
+ </ div >
369
+ ) }
370
+ </ div >
341
371
</ div >
342
372
) ;
343
373
} ,
0 commit comments