diff --git a/src/components/builder/AppBuilder.vue b/src/components/builder/AppBuilder.vue index d70b077bac..5c9b3367da 100644 --- a/src/components/builder/AppBuilder.vue +++ b/src/components/builder/AppBuilder.vue @@ -226,7 +226,7 @@ const renderedInputs = computed<[string, MaybeRef | undefined][]>( :class=" cn(dragClass, 'my-2 rounded-lg bg-primary-background/30 p-2') " - :title="entry.widget.label ?? entry.entityId" + :title="entry.widget.label ?? entry.displayName" :sub-title="entry.node.title" can-rename :remove="() => appModeStore.removeSelectedInput(entry.widget)" diff --git a/src/core/graph/subgraph/promotedWidgetView.ts b/src/core/graph/subgraph/promotedWidgetView.ts index d3f493074c..02fad6fb84 100644 --- a/src/core/graph/subgraph/promotedWidgetView.ts +++ b/src/core/graph/subgraph/promotedWidgetView.ts @@ -241,7 +241,10 @@ class PromotedWidgetView implements IPromotedWidgetView { */ ensureHostWidgetState(): void { if (this.getHostWidgetState()) return - this.registerHostWidgetState(this.resolveAtHost()?.widget.value) + // Seed from the effective promoted value (host → linked → deepest → + // interior fallback) instead of the raw interior default, so a restored + // promoted value isn't shadowed on first render. + this.registerHostWidgetState(this.value) } private registerHostWidgetState(value: IBaseWidget['value']): void { diff --git a/src/lib/litegraph/src/LGraphNode.ts b/src/lib/litegraph/src/LGraphNode.ts index 6b82ebaa3e..9247a5efb0 100644 --- a/src/lib/litegraph/src/LGraphNode.ts +++ b/src/lib/litegraph/src/LGraphNode.ts @@ -997,7 +997,16 @@ export class LGraphNode return o } - /* Creates a clone of this node */ + /** + * Creates a clone of this node. + * + * Note: between this call returning and `graph.add(clone)` running, the + * returned node briefly carries the **source node's id** rather than the + * historical `-1` sentinel. This is required so that subclass `configure()` + * implementations (e.g. {@link SubgraphNode}) which key per-instance state + * by id hydrate into the correct slot. `graph.add` will reassign a fresh id + * (or detect the collision and reassign) on insert. + */ clone(): LGraphNode | null { if (this.type == null) return null const node = LiteGraph.createNode(this.type) diff --git a/src/stores/appModeStore.test.ts b/src/stores/appModeStore.test.ts index 111114c840..7a4d2047b0 100644 --- a/src/stores/appModeStore.test.ts +++ b/src/stores/appModeStore.test.ts @@ -2,7 +2,7 @@ import { createTestingPinia } from '@pinia/testing' import { fromAny, fromPartial } from '@total-typescript/shoehorn' import { setActivePinia } from 'pinia' import { nextTick } from 'vue' -import { beforeEach, describe, expect, it, vi } from 'vitest' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import type { LGraphNode, NodeId } from '@/lib/litegraph/src/LGraphNode' import { SubgraphNode } from '@/lib/litegraph/src/litegraph' @@ -118,6 +118,12 @@ describe('appModeStore', () => { vi.clearAllMocks() }) + afterEach(() => { + // Restore any per-test spies (e.g. console.warn) so an assertion failure + // can't leak the spy into the next test. + vi.restoreAllMocks() + }) + describe('enterBuilder', () => { it('navigates to builder:arrange when in app mode with outputs', () => { workflowStore.activeWorkflow = createBuilderWorkflowWithOutputs('app')