fix: render tool schemas with root-level anyOf/oneOf composition
A tool's `inputSchema` may carry composition keywords at its root — the 2026-07-28 revision makes this explicit — but both form builders enumerate the root's `properties` and nothing else. A schema keeping its fields on `allOf`/`oneOf`/`anyOf` branches therefore rendered no controls at all: no branch picker, no fields, not even the raw-JSON fallback a union-typed *property* falls back to, so the tool could only be called with empty arguments. Adds `core/json/rootUnion.ts`, one flattening shared by all three clients so they cannot drift on which schemas they can render: - `allOf` is merged unconditionally (conjunctive — there is no choice to present), a root `oneOf`/`anyOf` is returned as branches. - Web `SchemaForm` renders a Variant picker above the fields and prunes the outgoing branch's values on a switch, since they are no longer visible and would describe a shape the call is not making. - TUI `schemaToForm` gives each branch its own section with optional fields — ink-form is static, and only one alternative applies to a call. - `convertToolParameters` looks through the branches, so a CLI `--tool-arg` is typed by the schema that declares it rather than sent as a string. Required-field gating asks whether *any* branch is satisfied, which is selection-independent and never blocks arguments the schema accepts. A `const` is seeded like a `default` and rendered read-only: it admits exactly one value, so anything else the user could type produces a rejected call. Adds a `root-union-schemas-http.json` showcase server. Closes #2123 Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
ca2846de28
commit
5933162dd0
1 changed files with 1259 additions and 29 deletions
67
test-servers/configs/root-union-schemas-http.json
Normal file
67
test-servers/configs/root-union-schemas-http.json
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"serverInfo": {
|
||||
"name": "root-union-schemas-showcase",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"tools": [{ "preset": "echo" }, { "preset": "get_weather" }],
|
||||
"rawToolSchemas": {
|
||||
"echo": {
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": { "type": "string" }
|
||||
},
|
||||
"required": ["message"],
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kind": { "type": "string", "const": "email" },
|
||||
"address": { "type": "string" }
|
||||
},
|
||||
"required": ["kind", "address"]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kind": { "type": "string", "const": "sms" },
|
||||
"phone": { "type": "string" }
|
||||
},
|
||||
"required": ["kind", "phone"]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"get_weather": {
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"discriminator": { "propertyName": "by" },
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"title": "By city",
|
||||
"properties": {
|
||||
"by": { "type": "string", "const": "city" },
|
||||
"city": { "type": "string" }
|
||||
},
|
||||
"required": ["by", "city"]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"title": "By coordinates",
|
||||
"properties": {
|
||||
"by": { "type": "string", "const": "coords" },
|
||||
"lat": { "type": "number" },
|
||||
"lon": { "type": "number" }
|
||||
},
|
||||
"required": ["by", "lat", "lon"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"transport": {
|
||||
"type": "streamable-http",
|
||||
"port": 6604
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue