@@ -528,3 +528,187 @@ func TestFlexibleArgumentsJSONMarshalUnmarshal(t *testing.T) {
528528 assert .Equal (t , "value1" , args ["key1" ])
529529 assert .Equal (t , float64 (123 ), args ["key2" ]) // JSON numbers are unmarshaled as float64
530530}
531+
532+ // TestNewItemsAPICompatibility tests that the new Items API functions
533+ // generate the same schema as the original Items() function with manual schema objects
534+ func TestNewItemsAPICompatibility (t * testing.T ) {
535+ tests := []struct {
536+ name string
537+ oldTool Tool
538+ newTool Tool
539+ }{
540+ {
541+ name : "WithStringItems basic" ,
542+ oldTool : NewTool ("old-string-array" ,
543+ WithDescription ("Tool with string array using old API" ),
544+ WithArray ("items" ,
545+ Description ("List of string items" ),
546+ Items (map [string ]any {
547+ "type" : "string" ,
548+ }),
549+ ),
550+ ),
551+ newTool : NewTool ("new-string-array" ,
552+ WithDescription ("Tool with string array using new API" ),
553+ WithArray ("items" ,
554+ Description ("List of string items" ),
555+ WithStringItems (),
556+ ),
557+ ),
558+ },
559+ {
560+ name : "WithStringEnumItems" ,
561+ oldTool : NewTool ("old-enum-array" ,
562+ WithDescription ("Tool with enum array using old API" ),
563+ WithArray ("status" ,
564+ Description ("Filter by status" ),
565+ Items (map [string ]any {
566+ "type" : "string" ,
567+ "enum" : []string {"active" , "inactive" , "pending" },
568+ }),
569+ ),
570+ ),
571+ newTool : NewTool ("new-enum-array" ,
572+ WithDescription ("Tool with enum array using new API" ),
573+ WithArray ("status" ,
574+ Description ("Filter by status" ),
575+ WithStringEnumItems ([]string {"active" , "inactive" , "pending" }),
576+ ),
577+ ),
578+ },
579+ {
580+ name : "WithStringItems with options" ,
581+ oldTool : NewTool ("old-string-with-opts" ,
582+ WithDescription ("Tool with string array with options using old API" ),
583+ WithArray ("names" ,
584+ Description ("List of names" ),
585+ Items (map [string ]any {
586+ "type" : "string" ,
587+ "minLength" : 1 ,
588+ "maxLength" : 50 ,
589+ }),
590+ ),
591+ ),
592+ newTool : NewTool ("new-string-with-opts" ,
593+ WithDescription ("Tool with string array with options using new API" ),
594+ WithArray ("names" ,
595+ Description ("List of names" ),
596+ WithStringItems (MinLength (1 ), MaxLength (50 )),
597+ ),
598+ ),
599+ },
600+ {
601+ name : "WithNumberItems basic" ,
602+ oldTool : NewTool ("old-number-array" ,
603+ WithDescription ("Tool with number array using old API" ),
604+ WithArray ("scores" ,
605+ Description ("List of scores" ),
606+ Items (map [string ]any {
607+ "type" : "number" ,
608+ }),
609+ ),
610+ ),
611+ newTool : NewTool ("new-number-array" ,
612+ WithDescription ("Tool with number array using new API" ),
613+ WithArray ("scores" ,
614+ Description ("List of scores" ),
615+ WithNumberItems (),
616+ ),
617+ ),
618+ },
619+ {
620+ name : "WithNumberItems with constraints" ,
621+ oldTool : NewTool ("old-number-with-constraints" ,
622+ WithDescription ("Tool with constrained number array using old API" ),
623+ WithArray ("ratings" ,
624+ Description ("List of ratings" ),
625+ Items (map [string ]any {
626+ "type" : "number" ,
627+ "minimum" : 0.0 ,
628+ "maximum" : 10.0 ,
629+ }),
630+ ),
631+ ),
632+ newTool : NewTool ("new-number-with-constraints" ,
633+ WithDescription ("Tool with constrained number array using new API" ),
634+ WithArray ("ratings" ,
635+ Description ("List of ratings" ),
636+ WithNumberItems (Min (0 ), Max (10 )),
637+ ),
638+ ),
639+ },
640+ {
641+ name : "WithBooleanItems basic" ,
642+ oldTool : NewTool ("old-boolean-array" ,
643+ WithDescription ("Tool with boolean array using old API" ),
644+ WithArray ("flags" ,
645+ Description ("List of feature flags" ),
646+ Items (map [string ]any {
647+ "type" : "boolean" ,
648+ }),
649+ ),
650+ ),
651+ newTool : NewTool ("new-boolean-array" ,
652+ WithDescription ("Tool with boolean array using new API" ),
653+ WithArray ("flags" ,
654+ Description ("List of feature flags" ),
655+ WithBooleanItems (),
656+ ),
657+ ),
658+ },
659+ }
660+
661+ for _ , tt := range tests {
662+ t .Run (tt .name , func (t * testing.T ) {
663+ // Marshal both tools to JSON
664+ oldData , err := json .Marshal (tt .oldTool )
665+ assert .NoError (t , err )
666+
667+ newData , err := json .Marshal (tt .newTool )
668+ assert .NoError (t , err )
669+
670+ // Unmarshal to maps for comparison
671+ var oldResult , newResult map [string ]any
672+ err = json .Unmarshal (oldData , & oldResult )
673+ assert .NoError (t , err )
674+
675+ err = json .Unmarshal (newData , & newResult )
676+ assert .NoError (t , err )
677+
678+ // Compare the inputSchema properties (ignoring tool names and descriptions)
679+ oldSchema := oldResult ["inputSchema" ].(map [string ]any )
680+ newSchema := newResult ["inputSchema" ].(map [string ]any )
681+
682+ oldProperties := oldSchema ["properties" ].(map [string ]any )
683+ newProperties := newSchema ["properties" ].(map [string ]any )
684+
685+ // Get the array property (should be the only one in these tests)
686+ var oldArrayProp , newArrayProp map [string ]any
687+ for _ , prop := range oldProperties {
688+ if propMap , ok := prop .(map [string ]any ); ok && propMap ["type" ] == "array" {
689+ oldArrayProp = propMap
690+ break
691+ }
692+ }
693+ for _ , prop := range newProperties {
694+ if propMap , ok := prop .(map [string ]any ); ok && propMap ["type" ] == "array" {
695+ newArrayProp = propMap
696+ break
697+ }
698+ }
699+
700+ assert .NotNil (t , oldArrayProp , "Old tool should have array property" )
701+ assert .NotNil (t , newArrayProp , "New tool should have array property" )
702+
703+ // Compare the items schema - this is the critical part
704+ oldItems := oldArrayProp ["items" ]
705+ newItems := newArrayProp ["items" ]
706+
707+ assert .Equal (t , oldItems , newItems , "Items schema should be identical between old and new API" )
708+
709+ // Also compare other array properties like description
710+ assert .Equal (t , oldArrayProp ["description" ], newArrayProp ["description" ], "Array descriptions should match" )
711+ assert .Equal (t , oldArrayProp ["type" ], newArrayProp ["type" ], "Array types should match" )
712+ })
713+ }
714+ }
0 commit comments