feat: auto-resolve simple validation errors on widget change and slot connection (#9464)

## Summary

Automatically clears transient validation errors
(`value_bigger_than_max`, `value_smaller_than_min`, `value_not_in_list`,
`required_input_missing`) when the user modifies a widget value or
connects an input slot, so resolved errors don't linger in the error
panel. Also clears missing model state when the user changes a combo
widget value.

## Changes

- **`useNodeErrorAutoResolve` composable**: watches widget changes and
slot connections, clears matching errors via `executionErrorStore`
- **`executionErrorStore`**: adds `clearSimpleNodeErrors` and
`clearSimpleWidgetErrorIfValid` with granular per-slot error removal
- **`executionErrorUtil`**: adds `isValueStillOutOfRange` to prevent
premature clearing when a new value still violates the constraint
- **`graphTraversalUtil`**: adds `getExecutionIdFromNodeData` for
subgraph-aware execution ID resolution
- **`GraphCanvas.vue`**: fixes subgraph error key lookup by using
`getExecutionIdByNode` instead of raw `node.id`
- **`NodeWidgets.vue`**: wires up the new composable to the widget layer
- **`missingModelStore`**: adds `removeMissingModelByWidget` to clear
missing model state on widget value change
- **`useGraphNodeManager`**: registers composable per node
- **Tests**: 126 new unit tests covering error clearing, range
validation, and graph traversal edge cases

## Screenshots



https://github.com/user-attachments/assets/515ea811-ff84-482a-a866-a17e5c779c39



https://github.com/user-attachments/assets/a2b30f02-4929-4537-952c-a0febe20f02e


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9464-feat-auto-resolve-simple-validation-errors-on-widget-change-and-slot-connection-31b6d73d3650816b8afdc34f4b40295a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jaeone94
2026-03-13 23:49:44 +09:00
committed by GitHub
parent d73f8e1beb
commit 31a33a0ba2
16 changed files with 1790 additions and 105 deletions

View File

@@ -388,6 +388,32 @@ describe('scanAllModelCandidates', () => {
expect(result[0].isAssetSupported).toBe(true)
expect(result[1].widgetName).toBe('vae_name')
})
it('skips subgraph container nodes whose promoted widgets are already scanned via interior nodes', () => {
const containerNode = {
id: 65,
type: 'abc-def-uuid',
widgets: [makeComboWidget('ckpt_name', 'model.safetensors', [])],
isSubgraphNode: () => true,
_testExecutionId: '65'
} as unknown as LGraphNode
const interiorNode = makeNode(
42,
'CheckpointLoaderSimple',
[
makeComboWidget('ckpt_name', 'model.safetensors', ['model.safetensors'])
],
'65:42'
)
const graph = makeGraph([containerNode, interiorNode])
const result = scanAllModelCandidates(graph, noAssetSupport)
expect(result).toHaveLength(1)
expect(result[0].nodeId).toBe('65:42')
expect(result[0].nodeType).toBe('CheckpointLoaderSimple')
})
})
function makeCandidate(