From d2917be3a7cd6e1297811a4e4dbedaee09c65427 Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Sat, 21 Feb 2026 22:29:28 -0800 Subject: [PATCH] feat: support custom descriptions for subgraph tooltips (#9003) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Adds support for custom descriptions on subgraph nodes that display as tooltips when hovering. ## Changes - Add optional `description` field to `ExportedSubgraph` interface and `Subgraph` class - Use description with fallback to default string in `subgraphService.createNodeDef()` - Add `description` to `SubgraphDefinitionBase` interface and Zod schema for validation ## Review Focus - Backwards compatibility: undefined description falls back to `Subgraph node for ${name}` - Serialization pattern: conditional spread `...(this.description && { description })` ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9003-feat-support-custom-descriptions-for-subgraph-tooltips-30d6d73d36508129bd75c77eb1c31cfb) by [Unito](https://www.unito.io) --- src/lib/litegraph/src/LGraph.ts | 6 +++++- .../litegraph/src/subgraph/SubgraphSerialization.test.ts | 1 - src/lib/litegraph/src/types/serialisation.ts | 2 ++ src/platform/workflow/validation/schemas/workflowSchema.ts | 4 ++++ src/services/subgraphService.ts | 2 +- 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/lib/litegraph/src/LGraph.ts b/src/lib/litegraph/src/LGraph.ts index 105bb9ff8..93a8fee64 100644 --- a/src/lib/litegraph/src/LGraph.ts +++ b/src/lib/litegraph/src/LGraph.ts @@ -2657,6 +2657,8 @@ export class Subgraph /** The display name of the subgraph. */ name: string = 'Unnamed Subgraph' + /** Optional description shown as tooltip when hovering over the subgraph node. */ + description?: string readonly inputNode = new SubgraphInputNode(this) readonly outputNode = new SubgraphOutputNode(this) @@ -2707,9 +2709,10 @@ export class Subgraph | (ISerialisedGraph & ExportedSubgraph) | (SerialisableGraph & ExportedSubgraph) ): void { - const { name, inputs, outputs, widgets } = data + const { name, description, inputs, outputs, widgets } = data this.name = name + this.description = description if (inputs) { this.inputs.length = 0 for (const input of inputs) { @@ -2920,6 +2923,7 @@ export class Subgraph revision: this.revision, config: this.config, name: this.name, + ...(this.description && { description: this.description }), inputNode: this.inputNode.asSerialisable(), outputNode: this.outputNode.asSerialisable(), inputs: this.inputs.map((x) => x.asSerialisable()), diff --git a/src/lib/litegraph/src/subgraph/SubgraphSerialization.test.ts b/src/lib/litegraph/src/subgraph/SubgraphSerialization.test.ts index f773fe63d..c2546bf12 100644 --- a/src/lib/litegraph/src/subgraph/SubgraphSerialization.test.ts +++ b/src/lib/litegraph/src/subgraph/SubgraphSerialization.test.ts @@ -76,7 +76,6 @@ describe.skip('SubgraphSerialization - Basic Serialization', () => { // Verify core properties expect(restored.id).toBe(original.id) expect(restored.name).toBe(original.name) - // @ts-expect-error description property not in type definition expect(restored.description).toBe(original.description) // Verify I/O structure diff --git a/src/lib/litegraph/src/types/serialisation.ts b/src/lib/litegraph/src/types/serialisation.ts index f34e9fcf8..ad7b76b84 100644 --- a/src/lib/litegraph/src/types/serialisation.ts +++ b/src/lib/litegraph/src/types/serialisation.ts @@ -139,6 +139,8 @@ export interface ExportedSubgraph extends SerialisableGraph { name: string /** Optional category for organizing subgraph blueprints in the node library. */ category?: string + /** Optional description shown as tooltip when hovering over the subgraph node. */ + description?: string inputNode: ExportedSubgraphIONode outputNode: ExportedSubgraphIONode /** Ordered list of inputs to the subgraph itself. Similar to a reroute, with the input side in the graph, and the output side in the subgraph. */ diff --git a/src/platform/workflow/validation/schemas/workflowSchema.ts b/src/platform/workflow/validation/schemas/workflowSchema.ts index 0db21b8c8..a6a6ee4ff 100644 --- a/src/platform/workflow/validation/schemas/workflowSchema.ts +++ b/src/platform/workflow/validation/schemas/workflowSchema.ts @@ -396,6 +396,8 @@ interface SubgraphDefinitionBase< id: string revision: number name: string + /** Optional description shown as tooltip when hovering over the subgraph node. */ + description?: string category?: string /** Custom metadata for the subgraph (description, searchAliases, etc.) */ extra?: T extends ComfyWorkflow1BaseInput @@ -432,6 +434,8 @@ const zSubgraphDefinition = zComfyWorkflow1 id: z.string().uuid(), revision: z.number(), name: z.string(), + /** Optional description shown as tooltip when hovering over the subgraph node. */ + description: z.string().optional(), category: z.string().optional(), inputNode: zExportedSubgraphIONode, outputNode: zExportedSubgraphIONode, diff --git a/src/services/subgraphService.ts b/src/services/subgraphService.ts index 3a9f1f7c7..068d3ed37 100644 --- a/src/services/subgraphService.ts +++ b/src/services/subgraphService.ts @@ -49,7 +49,7 @@ export const useSubgraphService = () => { output_tooltips: [], name: id, display_name: name, - description: `Subgraph node for ${name}`, + description: exportedSubgraph.description || `Subgraph node for ${name}`, category: 'subgraph', output_node: false, python_module: 'nodes'