From 92e01dca080fc835df9ff0c1efe651e866d3e7df Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Wed, 19 Nov 2025 17:38:11 -0800 Subject: [PATCH 1/2] fix: allow empty elicitation form data when all fields are optional --- client/src/utils/__tests__/schemaUtils.test.ts | 4 ++-- client/src/utils/schemaUtils.ts | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/client/src/utils/__tests__/schemaUtils.test.ts b/client/src/utils/__tests__/schemaUtils.test.ts index 98bfcb0bd..23475cce2 100644 --- a/client/src/utils/__tests__/schemaUtils.test.ts +++ b/client/src/utils/__tests__/schemaUtils.test.ts @@ -43,8 +43,8 @@ describe("generateDefaultValue", () => { expect(generateDefaultValue({ type: "array" })).toBe(undefined); }); - test("generates undefined for optional object", () => { - expect(generateDefaultValue({ type: "object" })).toBe(undefined); + test("generates empty object for optional root object", () => { + expect(generateDefaultValue({ type: "object" })).toEqual({}); }); test("generates default null for unknown types", () => { diff --git a/client/src/utils/schemaUtils.ts b/client/src/utils/schemaUtils.ts index 42d77d439..7e584c1e5 100644 --- a/client/src/utils/schemaUtils.ts +++ b/client/src/utils/schemaUtils.ts @@ -100,6 +100,7 @@ export function generateDefaultValue( propertyName && parentSchema ? isPropertyRequired(propertyName, parentSchema) : false; + const isRootSchema = propertyName === undefined && parentSchema === undefined; switch (schema.type) { case "string": @@ -112,7 +113,9 @@ export function generateDefaultValue( case "array": return isRequired ? [] : undefined; case "object": { - if (!schema.properties) return isRequired ? {} : undefined; + if (!schema.properties) { + return isRequired || isRootSchema ? {} : undefined; + } const obj: JsonObject = {}; // Only include properties that are required according to the schema's required array @@ -124,7 +127,11 @@ export function generateDefaultValue( } } }); - return isRequired ? obj : Object.keys(obj).length > 0 ? obj : undefined; + + if (Object.keys(obj).length === 0) { + return isRequired || isRootSchema ? {} : undefined; + } + return obj; } case "null": return null; From 4b20f15c72235d5e967407185f826ce2198e61ba Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Mon, 1 Dec 2025 10:07:10 -0800 Subject: [PATCH 2/2] add suggested tests from code review --- .../src/utils/__tests__/schemaUtils.test.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/client/src/utils/__tests__/schemaUtils.test.ts b/client/src/utils/__tests__/schemaUtils.test.ts index 23475cce2..2d1b686f9 100644 --- a/client/src/utils/__tests__/schemaUtils.test.ts +++ b/client/src/utils/__tests__/schemaUtils.test.ts @@ -47,6 +47,36 @@ describe("generateDefaultValue", () => { expect(generateDefaultValue({ type: "object" })).toEqual({}); }); + test("generates undefined for nested optional object", () => { + // When called WITH propertyName and parentSchema, and the property is NOT required, + // nested optional objects should return undefined + const parentSchema = { + type: "object" as const, + required: ["otherField"], + properties: { + optionalObject: { type: "object" as const }, + otherField: { type: "string" as const }, + }, + }; + expect( + generateDefaultValue({ type: "object" }, "optionalObject", parentSchema), + ).toBe(undefined); + }); + + test("generates empty object for root-level object with all optional properties", () => { + // Root-level schema with properties but no required array + // This is the exact scenario from PR #926 - elicitation with all optional fields + const schema: JsonSchemaType = { + type: "object", + properties: { + optionalField1: { type: "string" }, + optionalField2: { type: "number" }, + }, + // No required array - all fields are optional + }; + expect(generateDefaultValue(schema)).toEqual({}); + }); + test("generates default null for unknown types", () => { // @ts-expect-error Testing with invalid type expect(generateDefaultValue({ type: "unknown" })).toBe(undefined);