internal/mcp/jsonschema: remove shared structure from schema inference

Schemas must form a tree. This is important for Schema.Resolve, and
also for modifying parts of the schema before resolution, as with
mcp SchemaOptions.

Remove the `seen` argument from inference, creating all schemas
afresh.

Change-Id: Ief8295e8470f3f575ef51cc2ba697901250bbe6f
Reviewed-on: https://go-review.googlesource.com/c/tools/+/676937
Auto-Submit: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Hongxiang Jiang <hxjiang@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Jonathan Amsterdam 2025-05-28 14:41:55 -04:00 • committed by Gopher Robot
commit a9a69a03e4

View file

@ -44,21 +44,17 @@ func For[T any]() (*Schema, error) {
//
// TODO(rfindley): we could perhaps just skip these incompatible fields.
func ForType(t reflect.Type) (*Schema, error) {
return typeSchema(t, make(map[reflect.Type]*Schema))
return typeSchema(t)
}
func typeSchema(t reflect.Type, seen map[reflect.Type]*Schema) (*Schema, error) {
func typeSchema(t reflect.Type) (*Schema, error) {
if t.Kind() == reflect.Pointer {
t = t.Elem()
}
if s := seen[t]; s != nil {
return s, nil
}
var (
s = new(Schema)
err error
)
seen[t] = s
switch t.Kind() {
case reflect.Bool:
@ -80,14 +76,14 @@ func typeSchema(t reflect.Type, seen map[reflect.Type]*Schema) (*Schema, error)
return nil, fmt.Errorf("unsupported map key type %v", t.Key().Kind())
}
s.Type = "object"
s.AdditionalProperties, err = typeSchema(t.Elem(), seen)
s.AdditionalProperties, err = typeSchema(t.Elem())
if err != nil {
return nil, fmt.Errorf("computing map value schema: %v", err)
}
case reflect.Slice, reflect.Array:
s.Type = "array"
s.Items, err = typeSchema(t.Elem(), seen)
s.Items, err = typeSchema(t.Elem())
if err != nil {
return nil, fmt.Errorf("computing element schema: %v", err)
}
@ -113,7 +109,7 @@ func typeSchema(t reflect.Type, seen map[reflect.Type]*Schema) (*Schema, error)
if s.Properties == nil {
s.Properties = make(map[string]*Schema)
}
s.Properties[name], err = typeSchema(field.Type, seen)
s.Properties[name], err = typeSchema(field.Type)
if err != nil {
return nil, err
}