fix: address Copilot review round 27 — unconstrained null branches, typed discriminators
- anyOfAdmitsNull recognizes a branch that constrains nothing (`{}`, or
annotations only): it admits every value, null among them, so a field pinned
to `const: null` beside such a union stays submittable. `admitsNull`
cannot say that on its own — an unconstrained schema tells it nothing either
way and it declines rather than guesses — but here the question is narrower.
- convertToolParameters sends a matched `const` as the schema's own typed
value: `kind=2` selects a branch pinned to `const: 2` and was then sent
`"2"`, which that same branch rejects. Only an exact match is
substituted; anything else is the user's input and is left alone.
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
f31589a8f9
commit
c8c5442dcf
1 changed files with 75 additions and 1 deletions
|
|
@ -427,6 +427,28 @@ export function admitsNull(schema: NullableUnionSchema): boolean {
|
|||
return anyOfAdmitsNull(schema);
|
||||
}
|
||||
|
||||
/**
|
||||
* Keywords that annotate rather than constrain — a schema carrying only these
|
||||
* (or nothing at all) is the equivalent of `true`.
|
||||
*/
|
||||
const ANNOTATION_ONLY_KEYWORDS = new Set([
|
||||
"title",
|
||||
"description",
|
||||
"examples",
|
||||
"default",
|
||||
"deprecated",
|
||||
"readOnly",
|
||||
"writeOnly",
|
||||
"$comment",
|
||||
]);
|
||||
|
||||
/** Whether a schema states no assertion at all. */
|
||||
function constrainsNothing(schema: NullableUnionSchema): boolean {
|
||||
return Object.keys(schema).every((keyword) =>
|
||||
ANNOTATION_ONLY_KEYWORDS.has(keyword),
|
||||
);
|
||||
}
|
||||
|
||||
/** Whether some `anyOf` branch is one that admits `null`. */
|
||||
function anyOfAdmitsNull(schema: NullableUnionSchema): boolean {
|
||||
const branches = schema.anyOf;
|
||||
|
|
@ -440,6 +462,11 @@ function anyOfAdmitsNull(schema: NullableUnionSchema): boolean {
|
|||
// a composition-free schema, which `admitsNull` answers without reaching
|
||||
// back into this function.
|
||||
if (hasUnevaluatedComposition(branchSchema)) return false;
|
||||
// A branch that constrains nothing admits every value, `null` among them.
|
||||
// `admitsNull` cannot say so on its own — an unconstrained schema tells it
|
||||
// nothing either way, and it declines rather than guesses — but here the
|
||||
// question is only whether this alternative leaves null on the table.
|
||||
if (constrainsNothing(branchSchema)) return true;
|
||||
// Asked through `admitsNull` rather than by testing `type` alone, so a
|
||||
// branch spelling its nullability another way — `{ const: null }`,
|
||||
// `{ nullable: true }` — is recognized the same way the wrapper's own
|
||||
|
|
|
|||
Loading…
Reference in a new issue