|
4 | 4 | import Accordion from "./gradio/app/Accordion.svelte";
|
5 | 5 | import uiState from '$lib/stores/uiState';
|
6 | 6 | import type { ComfyNodeDefInputType } from "$lib/ComfyNodeDef";
|
7 |
| - import type { INodeInputSlot, LGraphNode, Subgraph } from "@litegraph-ts/core"; |
8 |
| - import { UpstreamNodeLocator } from "./ComfyPromptSerializer"; |
| 7 | + import type { INodeInputSlot, LGraphNode, LLink, Subgraph } from "@litegraph-ts/core"; |
| 8 | + import { UpstreamNodeLocator, getUpstreamLink, nodeHasTag } from "./ComfyPromptSerializer"; |
9 | 9 | import JsonView from "./JsonView.svelte";
|
10 | 10 |
|
11 | 11 | export let app: ComfyApp;
|
12 | 12 | export let errors: ComfyGraphErrors;
|
13 | 13 |
|
| 14 | + let missingTag = null; |
| 15 | + let nodeToJumpTo = null; |
| 16 | + let inputSlotToHighlight = null; |
| 17 | + let _errors = null |
| 18 | +
|
| 19 | + $: if (_errors != errors) { |
| 20 | + _errors = errors; |
| 21 | + if (errors.errors[0]) { |
| 22 | + jumpToError(errors.errors[0]) |
| 23 | + } |
| 24 | + } |
| 25 | +
|
14 | 26 | function closeList() {
|
15 | 27 | app.lCanvas.clearErrors();
|
16 | 28 | $uiState.activeError = null;
|
| 29 | + clearState() |
| 30 | + } |
| 31 | +
|
| 32 | + function clearState() { |
| 33 | + _errors = null; |
| 34 | + missingTag = null; |
| 35 | + nodeToJumpTo = null; |
| 36 | + inputSlotToHighlight = null; |
17 | 37 | }
|
18 | 38 |
|
19 | 39 | function getParentNode(error: ComfyGraphErrorLocation): Subgraph | null {
|
|
24 | 44 | return node.graph._subgraph_node
|
25 | 45 | }
|
26 | 46 |
|
27 |
| - function canJumpToDisconnectedInput(error: ComfyGraphErrorLocation): boolean { |
28 |
| - return error.errorType === ComfyNodeErrorType.RequiredInputMissing && error.input != null; |
| 47 | + function jumpToFoundNode() { |
| 48 | + if (nodeToJumpTo == null) { |
| 49 | + return |
| 50 | + } |
| 51 | +
|
| 52 | + app.lCanvas.jumpToNodeAndInput(nodeToJumpTo, inputSlotToHighlight); |
29 | 53 | }
|
30 | 54 |
|
31 |
| - function jumpToDisconnectedInput(error: ComfyGraphErrorLocation) { |
| 55 | + function detectDisconnected(error: ComfyGraphErrorLocation) { |
| 56 | + missingTag = null; |
| 57 | + nodeToJumpTo = null; |
| 58 | + inputSlotToHighlight = null; |
| 59 | +
|
32 | 60 | if (error.errorType !== ComfyNodeErrorType.RequiredInputMissing || error.input == null) {
|
33 | 61 | return
|
34 | 62 | }
|
35 | 63 |
|
36 | 64 | const node = app.lCanvas.graph.getNodeByIdRecursive(error.nodeID);
|
37 | 65 |
|
38 |
| - const inputIndex =node.findInputSlotIndexByName(error.input.name); |
| 66 | + const inputIndex = node.findInputSlotIndexByName(error.input.name); |
39 | 67 | if (inputIndex === -1) {
|
40 | 68 | return
|
41 | 69 | }
|
42 | 70 |
|
43 | 71 | // TODO multiple tags?
|
44 | 72 | const tag: string | null = error.queueEntry.extraData.extra_pnginfo.comfyBoxPrompt.subgraphs[0];
|
45 | 73 |
|
46 |
| - const test = (node: LGraphNode) => (node as any).isBackendNode |
| 74 | + const test = (node: LGraphNode, currentLink: LLink) => { |
| 75 | + if (!nodeHasTag(node, tag, true)) |
| 76 | + return true; |
| 77 | +
|
| 78 | + const [nextGraph, nextLink, nextInputSlot, nextNode] = getUpstreamLink(node, currentLink) |
| 79 | + return nextLink == null; |
| 80 | + }; |
47 | 81 | const nodeLocator = new UpstreamNodeLocator(test)
|
48 |
| - const [_, foundLink, foundInputSlot, foundPrevNode] = nodeLocator.locateUpstream(node, inputIndex, tag); |
| 82 | + const [foundNode, foundLink, foundInputSlot, foundPrevNode] = nodeLocator.locateUpstream(node, inputIndex, null); |
49 | 83 |
|
50 | 84 | if (foundInputSlot != null && foundPrevNode != null) {
|
51 |
| - app.lCanvas.jumpToNodeAndInput(foundPrevNode, foundInputSlot); |
| 85 | + if (!nodeHasTag(foundNode, tag, true)) { |
| 86 | + nodeToJumpTo = foundNode |
| 87 | + missingTag = tag; |
| 88 | + inputSlotToHighlight = null; |
| 89 | + } |
| 90 | + else { |
| 91 | + nodeToJumpTo = foundPrevNode; |
| 92 | + inputSlotToHighlight = foundInputSlot; |
| 93 | + } |
52 | 94 | }
|
53 | 95 | }
|
54 | 96 |
|
55 | 97 | function jumpToError(error: ComfyGraphErrorLocation) {
|
56 | 98 | app.lCanvas.jumpToError(error);
|
| 99 | +
|
| 100 | + detectDisconnected(error); |
57 | 101 | }
|
58 | 102 |
|
59 | 103 | function getInputTypeName(type: ComfyNodeDefInputType) {
|
|
88 | 132 | <div class="error-details">
|
89 | 133 | <button class="jump-to-error" class:execution-error={isExecutionError} on:click={() => jumpToError(error)}><span>⮎</span></button>
|
90 | 134 | <div class="error-details-wrapper">
|
91 |
| - <span class="error-message" class:execution-error={isExecutionError}>{error.message}</span> |
| 135 | + {#if missingTag && nodeToJumpTo} |
| 136 | + <div class="error-input"> |
| 137 | + <div><span class="error-message">Node "{nodeToJumpTo.title}" was missing tag used in workflow:</span><span style:padding-left="0.2rem"><b>{missingTag}</b></span></div> |
| 138 | + <div>Tags on node: <b>{(nodeToJumpTo?.properties?.tags || []).join(", ")}</b></div> |
| 139 | + </div> |
| 140 | + {:else} |
| 141 | + <span class="error-message" class:execution-error={isExecutionError}>{error.message}</span> |
| 142 | + {/if} |
92 | 143 | {#if error.exceptionType}
|
93 | 144 | <span>({error.exceptionType})</span>
|
94 | 145 | {/if}
|
95 | 146 | {#if error.exceptionMessage && !isExecutionError}
|
96 | 147 | <div style:text-decoration="underline">{error.exceptionMessage}</div>
|
97 | 148 | {/if}
|
98 |
| - {#if error.input} |
| 149 | + {#if nodeToJumpTo != null} |
| 150 | + <div style:display="flex" style:flex-direction="row"> |
| 151 | + <button class="jump-to-error locate" on:click={jumpToFoundNode}><span>⮎</span></button> |
| 152 | + {#if missingTag} |
| 153 | + <span>Jump to node: {nodeToJumpTo.title}</span> |
| 154 | + {:else} |
| 155 | + <span>Find disconnected input</span> |
| 156 | + {/if} |
| 157 | + </div> |
| 158 | + {/if} |
| 159 | + {#if error.input && !missingTag} |
99 | 160 | <div class="error-input">
|
100 | 161 | <span>Input: <b>{error.input.name}</b></span>
|
101 | 162 | {#if error.input.config}
|
102 | 163 | <span>({getInputTypeName(error.input.config[0])})</span>
|
103 | 164 | {/if}
|
104 | 165 | </div>
|
105 |
| - {#if canJumpToDisconnectedInput(error)} |
106 |
| - <div style:display="flex" style:flex-direction="row"> |
107 |
| - <button class="jump-to-error locate" on:click={() => jumpToDisconnectedInput(error)}><span>⮎</span></button> |
108 |
| - <span>Find disconnected input</span> |
109 |
| - </div> |
110 |
| - {/if} |
111 | 166 |
|
112 | 167 | {#if error.input.receivedValue}
|
113 | 168 | <div>
|
|
0 commit comments