@@ -3148,6 +3148,8 @@ const toolTestState = {
3148
3148
requestTimeout : 30000 , // Increased from 10000ms
3149
3149
} ;
3150
3150
3151
+ let toolInputSchemaRegistry = null ;
3152
+
3151
3153
/**
3152
3154
* ENHANCED: Tool testing with improved race condition handling
3153
3155
*/
@@ -3243,6 +3245,7 @@ async function testTool(toolId) {
3243
3245
}
3244
3246
3245
3247
const tool = await response . json ( ) ;
3248
+ toolInputSchemaRegistry = tool ;
3246
3249
3247
3250
// 7. CLEAN STATE before proceeding
3248
3251
toolTestState . activeRequests . delete ( toolId ) ;
@@ -3326,20 +3329,91 @@ async function testTool(toolId) {
3326
3329
input . className =
3327
3330
"mt-1 block w-full rounded-md border border-gray-500 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 text-gray-700 dark:text-gray-300 dark:border-gray-700 dark:focus:border-indigo-400 dark:focus:ring-indigo-400" ;
3328
3331
3329
- // Add validation based on type
3330
- if ( prop . type === "number" ) {
3331
- input . type = "number" ;
3332
- } else if ( prop . type === "boolean" ) {
3333
- input . type = "checkbox" ;
3332
+ if ( prop . type === "array" ) {
3333
+ const arrayContainer = document . createElement ( "div" ) ;
3334
+ arrayContainer . className = "space-y-2" ;
3335
+
3336
+ function createArrayInput ( value = "" ) {
3337
+ const wrapper = document . createElement ( "div" ) ;
3338
+ wrapper . className = "flex items-center space-x-2" ;
3339
+
3340
+ const input = document . createElement ( "input" ) ;
3341
+ input . name = keyValidation . value ;
3342
+ input . required =
3343
+ schema . required && schema . required . includes ( key ) ;
3344
+ input . className =
3345
+ "mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 text-gray-700 dark:text-gray-300 dark:border-gray-700 dark:focus:border-indigo-400 dark:focus:ring-indigo-400" ;
3346
+ if ( prop . items && prop . items . type === "number" ) {
3347
+ input . type = "number" ;
3348
+ } else if (
3349
+ prop . items &&
3350
+ prop . items . type === "boolean"
3351
+ ) {
3352
+ input . type = "checkbox" ;
3353
+ input . value = "true" ;
3354
+ input . checked = value === true || value === "true" ;
3355
+ } else {
3356
+ input . type = "text" ;
3357
+ }
3358
+ if (
3359
+ typeof value === "string" ||
3360
+ typeof value === "number"
3361
+ ) {
3362
+ input . value = value ;
3363
+ }
3364
+
3365
+ const delBtn = document . createElement ( "button" ) ;
3366
+ delBtn . type = "button" ;
3367
+ delBtn . className =
3368
+ "ml-2 text-red-600 hover:text-red-800 focus:outline-none" ;
3369
+ delBtn . title = "Delete" ;
3370
+ delBtn . textContent = "×" ;
3371
+ delBtn . addEventListener ( "click" , ( ) => {
3372
+ arrayContainer . removeChild ( wrapper ) ;
3373
+ } ) ;
3374
+
3375
+ wrapper . appendChild ( input ) ;
3376
+ wrapper . appendChild ( delBtn ) ;
3377
+ return wrapper ;
3378
+ }
3379
+
3380
+ const addBtn = document . createElement ( "button" ) ;
3381
+ addBtn . type = "button" ;
3382
+ addBtn . className =
3383
+ "mt-2 px-2 py-1 bg-indigo-500 text-white rounded hover:bg-indigo-600 focus:outline-none" ;
3384
+ addBtn . textContent = "Add items" ;
3385
+ addBtn . addEventListener ( "click" , ( ) => {
3386
+ arrayContainer . appendChild ( createArrayInput ( ) ) ;
3387
+ } ) ;
3388
+
3389
+ arrayContainer . appendChild ( createArrayInput ( ) ) ;
3390
+
3391
+ fieldDiv . appendChild ( arrayContainer ) ;
3392
+ fieldDiv . appendChild ( addBtn ) ;
3393
+ } else {
3394
+ // Input field with validation
3395
+ const input = document . createElement ( "input" ) ;
3396
+ input . name = keyValidation . value ;
3397
+ input . required =
3398
+ schema . required && schema . required . includes ( key ) ;
3334
3399
input . className =
3335
- "mt-1 h-4 w-4 text-indigo-600 dark:text-indigo-200 border border-gray-300 rounded" ;
3400
+ "mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 text-gray-700 dark:text-gray-300 dark:border-gray-700 dark:focus:border-indigo-400 dark:focus:ring-indigo-400" ;
3401
+ // Add validation based on type
3402
+ if ( prop . type === "text" ) {
3403
+ input . type = "text" ;
3404
+ } else if ( prop . type === "number" ) {
3405
+ input . type = "number" ;
3406
+ } else if ( prop . type === "boolean" ) {
3407
+ input . type = "checkbox" ;
3408
+ input . className =
3409
+ "mt-1 h-4 w-4 text-indigo-600 dark:text-indigo-200 border border-gray-300 rounded" ;
3410
+ }
3411
+ fieldDiv . appendChild ( input ) ;
3336
3412
}
3337
3413
3338
- fieldDiv . appendChild ( input ) ;
3339
3414
container . appendChild ( fieldDiv ) ;
3340
3415
}
3341
3416
}
3342
-
3343
3417
openModal ( "tool-test-modal" ) ;
3344
3418
console . log ( "✓ Tool test modal loaded successfully" ) ;
3345
3419
} catch ( error ) {
@@ -3421,27 +3495,52 @@ async function runToolTest() {
3421
3495
const formData = new FormData ( form ) ;
3422
3496
const params = { } ;
3423
3497
3424
- for ( const [ key , value ] of formData . entries ( ) ) {
3425
- // Validate each parameter
3426
- const keyValidation = validateInputName ( key , "parameter" ) ;
3427
- if ( ! keyValidation . valid ) {
3428
- console . warn ( `Skipping invalid parameter: ${ key } ` ) ;
3429
- continue ;
3430
- }
3498
+ const schema = toolInputSchemaRegistry . inputSchema ;
3431
3499
3432
- // Type conversion
3433
- if ( isNaN ( value ) || value === "" ) {
3434
- if (
3435
- value . toLowerCase ( ) === "true" ||
3436
- value . toLowerCase ( ) === "false"
3437
- ) {
3438
- params [ keyValidation . value ] =
3439
- value . toLowerCase ( ) === "true" ;
3440
- } else {
3500
+ if ( schema && schema . properties ) {
3501
+ for ( const key in schema . properties ) {
3502
+ const prop = schema . properties [ key ] ;
3503
+ const keyValidation = validateInputName ( key , "parameter" ) ;
3504
+ if ( ! keyValidation . valid ) {
3505
+ console . warn ( `Skipping invalid parameter: ${ key } ` ) ;
3506
+ continue ;
3507
+ }
3508
+ let value ;
3509
+ if ( prop . type === "array" ) {
3510
+ value = formData . getAll ( key ) ;
3511
+ if ( prop . items && prop . items . type === "number" ) {
3512
+ value = value . map ( ( v ) => ( v === "" ? null : Number ( v ) ) ) ;
3513
+ } else if ( prop . items && prop . items . type === "boolean" ) {
3514
+ value = value . map ( ( v ) => v === "true" || v === true ) ;
3515
+ }
3516
+ if (
3517
+ value . length === 0 ||
3518
+ ( value . length === 1 && value [ 0 ] === "" )
3519
+ ) {
3520
+ continue ;
3521
+ }
3441
3522
params [ keyValidation . value ] = value ;
3523
+ } else {
3524
+ value = formData . get ( key ) ;
3525
+ if ( value === null || value === undefined || value === "" ) {
3526
+ if ( schema . required && schema . required . includes ( key ) ) {
3527
+ params [ keyValidation . value ] = "" ;
3528
+ }
3529
+ continue ;
3530
+ }
3531
+ if ( prop . type === "number" || prop . type === "integer" ) {
3532
+ params [ keyValidation . value ] = Number ( value ) ;
3533
+ } else if ( prop . type === "boolean" ) {
3534
+ params [ keyValidation . value ] =
3535
+ value === "true" || value === true ;
3536
+ } else if ( prop . enum ) {
3537
+ if ( prop . enum . includes ( value ) ) {
3538
+ params [ keyValidation . value ] = value ;
3539
+ }
3540
+ } else {
3541
+ params [ keyValidation . value ] = value ;
3542
+ }
3442
3543
}
3443
- } else {
3444
- params [ keyValidation . value ] = Number ( value ) ;
3445
3544
}
3446
3545
}
3447
3546
0 commit comments