diff --git a/src/types/comfyWorkflow.ts b/src/types/comfyWorkflow.ts index e1b5e20bd..c9a8e9705 100644 --- a/src/types/comfyWorkflow.ts +++ b/src/types/comfyWorkflow.ts @@ -49,6 +49,15 @@ const zVector2 = z.union([ z.tuple([z.number(), z.number()]), ]); +const zWidgetValues = z.union([ + z.array(z.any()), + z.record(z.any()).transform((v) => + Object.keys(v) + .sort((a, b) => Number(a) - Number(b)) + .map((key) => v[key]) + ), +]); + const zComfyNode = z .object({ id: z.number(), @@ -61,7 +70,7 @@ const zComfyNode = z inputs: z.array(zNodeInput).optional(), outputs: z.array(zNodeOutput).optional(), properties: zProperties, - widgets_values: z.array(z.any()).optional(), // This could contain mixed types + widgets_values: zWidgetValues.optional(), color: z.string().optional(), bgcolor: z.string().optional(), }) diff --git a/tests-ui/tests/comfyWorkflow.test.ts b/tests-ui/tests/comfyWorkflow.test.ts index f35b8d85d..87f74655a 100644 --- a/tests-ui/tests/comfyWorkflow.test.ts +++ b/tests-ui/tests/comfyWorkflow.test.ts @@ -70,4 +70,21 @@ describe("parseComfyWorkflow", () => { parsedWorkflow = await parseComfyWorkflow(JSON.stringify(workflow)); expect(parsedWorkflow.nodes[0].pos).toEqual([3, 4]); }); + + it("workflow.nodes.widget_values", async () => { + const workflow = JSON.parse(JSON.stringify(defaultGraph)); + workflow.nodes[0].widgets_values = ["foo", "bar"]; + await expect(parseComfyWorkflow(JSON.stringify(workflow))).resolves.not.toThrow(); + + workflow.nodes[0].widgets_values = "foo"; + await expect(parseComfyWorkflow(JSON.stringify(workflow))).rejects.toThrow(); + + workflow.nodes[0].widgets_values = undefined; + await expect(parseComfyWorkflow(JSON.stringify(workflow))).resolves.not.toThrow(); + + // Should automatically transform the legacy format object to array. + workflow.nodes[0].widgets_values = {0: "foo", 1: "bar"}; + const parsedWorkflow = await parseComfyWorkflow(JSON.stringify(workflow)); + expect(parsedWorkflow.nodes[0].widgets_values).toEqual(["foo", "bar"]); + }); });