Skip to content

Add schema builders to Unity#81

Open
thorminate wants to merge 7 commits intoVedalAI:mainfrom
thorminate:feat/schema-builder
Open

Add schema builders to Unity#81
thorminate wants to merge 7 commits intoVedalAI:mainfrom
thorminate:feat/schema-builder

Conversation

@thorminate
Copy link

@thorminate thorminate commented Jan 29, 2026

Adds a highly extensible and readable schema builder for the unity sdk.

Fully backward-compatible.

Here is an example with the old system:

protected override JsonSchema Schema =>
    QJS.WrapObject(
        new Dictionary<string, JsonSchema>
        {
            ["action"] = QJS.Enum(new[] { "move", "attack", "look_at" }),
            ["target"] = QJS.Type(JsonSchemaType.String),
            ["parameters"] = QJS.WrapObject(
                new Dictionary<string, JsonSchema>
                {
                    ["speed"] = QJS.Type(JsonSchemaType.Float),
                    ["direction"] = QJS.WrapObject(
                        new Dictionary<string, JsonSchema>
                        {
                            ["x"] = QJS.Type(JsonSchemaType.Float),
                            ["y"] = QJS.Type(JsonSchemaType.Float)
                        }
                    )
                },
                makePropertiesRequired: false
            ),
            ["flags"] = QJS.WrapObject(
                new Dictionary<string, JsonSchema>
                {
                    ["silent"] = QJS.Type(JsonSchemaType.Boolean)
                }
            )
        }
    );

and here is with the new builder system

protected override JsonSchema Schema =>
    QJS.Builder.Object()
        .Property("action", b => b.String().Enum("move", "attack", "look_at"))
        .Property("target", b => b.String())
        .Property("parameters", b => b.Object()
            .Property("speed", b => b.Float(), required: false)
            .Property("direction", b => b.Object()
                    .Property("x", b => b.Float())
                    .Property("y", b => b.Float()),
                required: false
            )
        )
        .Property("flags", b => b.Object()
            .Property("silent", b2 => b2.Boolean())
        )
        .Build();

In the base QJS wrapper you cannot make the root an array, so a little workaround would be:

protected override JsonSchema Schema => new JsonSchema
{
    Type = JsonSchemaType.Array,
    Items = new JsonSchema
    {
        Type = JsonSchemaType.Object,
        Properties = new Dictionary<string, JsonSchema>
        {
            ["id"] = new JsonSchema { Type = JsonSchemaType.Integer },
            ["name"] = new JsonSchema { Type = JsonSchemaType.String },
            ["tags"] = new JsonSchema
            {
                Type = JsonSchemaType.Array,
                Items = new JsonSchema { Type = JsonSchemaType.String }
            }
        },
        Required = new List<string> { "id", "name", "tags" }
    }
};

In the builders however, you can do that natively:

QJS.Builder
    .Array(b => b.Object()
        .Property("id", b => b.Integer())
        .Property("name", b => b.String())
        .Property("tags", b => b.Array()
                .Items(b => b.String())
        )
    )
    .Build();

All and all, with these changes along with my other pull requests, this should help encourage making proper schemas and give better information to neuro so she can better understand how the data should be formed

@thorminate thorminate changed the title Add schema builders Add schema builders to unity Jan 29, 2026
@thorminate thorminate changed the title Add schema builders to unity Add schema builders to Unity Jan 29, 2026
@Pasu4
Copy link
Contributor

Pasu4 commented Jan 29, 2026

In the base QJS wrapper you cannot make the root an array

The reason for that is that it is specified that the root must be of type object. So having the root be of type array should probably also be prevented with the new builders, to avoid going against the specification by accident.

For reference: API/SPECIFICATION.md#action.

@thorminate
Copy link
Author

thorminate commented Jan 29, 2026

In the base QJS wrapper you cannot make the root an array

The reason for that is that it is specified that the root must be of type object. So having the root be of type array should probably also be prevented with the new builders, to avoid going against the specification by accident.

For reference: API/SPECIFICATION.md#action.

i mean the string is directly provided by neuro and it has to be a json, arrays are valid json so i dont see what prevents it.

I do still see your point however

If you provide a schema, it must be of type "object".

is kind of a limitation, but since it will be directly received by neuro i think she can handle that fine, it is still json after all.

technically the schema can be set to a primitive type so i guess i have to go and set some limitations

@thorminate
Copy link
Author

There, i limited the root builders to only arrays and objects

@KTrain5169
Copy link
Contributor

I do still see your point however

If you provide a schema, it must be of type "object".

is kind of a limitation, but since it will be directly received by neuro i think she can handle that fine, it is still json after all.

technically the schema can be set to a primitive type so i guess i have to go and set some limitations

in theory this is possible and in theory neuro can work with it, however the spec only gets amended if it's for "certain" it works afaik, so if the spec is "only objects for top-level schemas", it's likely they tried non-object schemas for the top-level and it didn't work.

(I remember alex on the discord server testing top-level string schema type with the inscryption mod, so I think what happened is that he and/or vedal did some testing and found out that neuro doesn't really "understand" schemas that aren't type: "object", though take that with as many grains of salt as you wish because I wouldn't know for sure what happened)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants