temp journey view
This commit is contained in:
@@ -34,6 +34,8 @@
|
|||||||
"svelte-check": "^3.2.0",
|
"svelte-check": "^3.2.0",
|
||||||
"svelte-dnd-action": "^0.9.22",
|
"svelte-dnd-action": "^0.9.22",
|
||||||
"typescript": "^5.0.3",
|
"typescript": "^5.0.3",
|
||||||
|
"@types/cytoscape": "^3.19.9",
|
||||||
|
"@types/dompurify": "^3.0.2",
|
||||||
"vite": "^4.3.8",
|
"vite": "^4.3.8",
|
||||||
"vite-plugin-glsl": "^1.1.2",
|
"vite-plugin-glsl": "^1.1.2",
|
||||||
"vite-plugin-static-copy": "^0.14.0",
|
"vite-plugin-static-copy": "^0.14.0",
|
||||||
@@ -74,13 +76,14 @@
|
|||||||
"@litegraph-ts/tsconfig": "workspace:*",
|
"@litegraph-ts/tsconfig": "workspace:*",
|
||||||
"@sveltejs/vite-plugin-svelte": "^2.1.1",
|
"@sveltejs/vite-plugin-svelte": "^2.1.1",
|
||||||
"@tsconfig/svelte": "^4.0.1",
|
"@tsconfig/svelte": "^4.0.1",
|
||||||
"@types/dompurify": "^3.0.2",
|
|
||||||
"canvas-to-svg": "^1.0.3",
|
"canvas-to-svg": "^1.0.3",
|
||||||
"cm6-theme-basic-dark": "^0.2.0",
|
"cm6-theme-basic-dark": "^0.2.0",
|
||||||
"cm6-theme-basic-light": "^0.2.0",
|
"cm6-theme-basic-light": "^0.2.0",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
"csv": "^6.3.0",
|
"csv": "^6.3.0",
|
||||||
"csv-parse": "^5.3.10",
|
"csv-parse": "^5.3.10",
|
||||||
|
"cytoscape": "^3.25.0",
|
||||||
|
"cytoscape-dagre": "^2.5.0",
|
||||||
"dompurify": "^3.0.3",
|
"dompurify": "^3.0.3",
|
||||||
"events": "^3.3.0",
|
"events": "^3.3.0",
|
||||||
"framework7": "^8.0.3",
|
"framework7": "^8.0.3",
|
||||||
|
|||||||
57
pnpm-lock.yaml
generated
57
pnpm-lock.yaml
generated
@@ -97,9 +97,6 @@ importers:
|
|||||||
'@tsconfig/svelte':
|
'@tsconfig/svelte':
|
||||||
specifier: ^4.0.1
|
specifier: ^4.0.1
|
||||||
version: 4.0.1
|
version: 4.0.1
|
||||||
'@types/dompurify':
|
|
||||||
specifier: ^3.0.2
|
|
||||||
version: 3.0.2
|
|
||||||
canvas-to-svg:
|
canvas-to-svg:
|
||||||
specifier: ^1.0.3
|
specifier: ^1.0.3
|
||||||
version: 1.0.3
|
version: 1.0.3
|
||||||
@@ -118,6 +115,12 @@ importers:
|
|||||||
csv-parse:
|
csv-parse:
|
||||||
specifier: ^5.3.10
|
specifier: ^5.3.10
|
||||||
version: 5.3.10
|
version: 5.3.10
|
||||||
|
cytoscape:
|
||||||
|
specifier: ^3.25.0
|
||||||
|
version: 3.25.0
|
||||||
|
cytoscape-dagre:
|
||||||
|
specifier: ^2.5.0
|
||||||
|
version: 2.5.0(cytoscape@3.25.0)
|
||||||
dompurify:
|
dompurify:
|
||||||
specifier: ^3.0.3
|
specifier: ^3.0.3
|
||||||
version: 3.0.3
|
version: 3.0.3
|
||||||
@@ -188,6 +191,12 @@ importers:
|
|||||||
'@floating-ui/dom':
|
'@floating-ui/dom':
|
||||||
specifier: ^1.2.8
|
specifier: ^1.2.8
|
||||||
version: 1.2.8
|
version: 1.2.8
|
||||||
|
'@types/cytoscape':
|
||||||
|
specifier: ^3.19.9
|
||||||
|
version: 3.19.9
|
||||||
|
'@types/dompurify':
|
||||||
|
specifier: ^3.0.2
|
||||||
|
version: 3.0.2
|
||||||
'@zerodevx/svelte-toast':
|
'@zerodevx/svelte-toast':
|
||||||
specifier: ^0.9.3
|
specifier: ^0.9.3
|
||||||
version: 0.9.3(svelte@3.59.1)
|
version: 0.9.3(svelte@3.59.1)
|
||||||
@@ -2368,6 +2377,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==}
|
resolution: {integrity: sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/cytoscape@3.19.9:
|
||||||
|
resolution: {integrity: sha512-oqCx0ZGiBO0UESbjgq052vjDAy2X53lZpMrWqiweMpvVwKw/2IiYDdzPFK6+f4tMfdv9YKEM9raO5bAZc3UYBg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/d3-dsv@3.0.0:
|
/@types/d3-dsv@3.0.0:
|
||||||
resolution: {integrity: sha512-o0/7RlMl9p5n6FQDptuJVMxDf/7EDEv2SYEO/CwdG2tr1hTfUVi0Iavkk2ax+VpaQ/1jVhpnj5rq1nj8vwhn2A==}
|
resolution: {integrity: sha512-o0/7RlMl9p5n6FQDptuJVMxDf/7EDEv2SYEO/CwdG2tr1hTfUVi0Iavkk2ax+VpaQ/1jVhpnj5rq1nj8vwhn2A==}
|
||||||
|
|
||||||
@@ -2395,7 +2408,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-YBL4ziFebbbfQfH5mlC+QTJsvh0oJUrWbmxKMyEdL7emlHJqGR2Qb34TEFKj+VCayBvjKy3xczMFNhugThUsfQ==}
|
resolution: {integrity: sha512-YBL4ziFebbbfQfH5mlC+QTJsvh0oJUrWbmxKMyEdL7emlHJqGR2Qb34TEFKj+VCayBvjKy3xczMFNhugThUsfQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/trusted-types': 2.0.3
|
'@types/trusted-types': 2.0.3
|
||||||
dev: false
|
dev: true
|
||||||
|
|
||||||
/@types/estree@1.0.1:
|
/@types/estree@1.0.1:
|
||||||
resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==}
|
resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==}
|
||||||
@@ -2482,7 +2495,7 @@ packages:
|
|||||||
|
|
||||||
/@types/trusted-types@2.0.3:
|
/@types/trusted-types@2.0.3:
|
||||||
resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==}
|
resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==}
|
||||||
dev: false
|
dev: true
|
||||||
|
|
||||||
/@types/uuid@9.0.1:
|
/@types/uuid@9.0.1:
|
||||||
resolution: {integrity: sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==}
|
resolution: {integrity: sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==}
|
||||||
@@ -3324,6 +3337,23 @@ packages:
|
|||||||
stream-transform: 3.2.6
|
stream-transform: 3.2.6
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/cytoscape-dagre@2.5.0(cytoscape@3.25.0):
|
||||||
|
resolution: {integrity: sha512-VG2Knemmshop4kh5fpLO27rYcyUaaDkRw+6PiX4bstpB+QFt0p2oauMrsjVbUamGWQ6YNavh7x2em2uZlzV44g==}
|
||||||
|
peerDependencies:
|
||||||
|
cytoscape: ^3.2.22
|
||||||
|
dependencies:
|
||||||
|
cytoscape: 3.25.0
|
||||||
|
dagre: 0.8.5
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/cytoscape@3.25.0:
|
||||||
|
resolution: {integrity: sha512-7MW3Iz57mCUo6JQCho6CmPBCbTlJr7LzyEtIkutG255HLVd4XuBg2I9BkTZLI/e4HoaOB/BiAzXuQybQ95+r9Q==}
|
||||||
|
engines: {node: '>=0.10'}
|
||||||
|
dependencies:
|
||||||
|
heap: 0.2.7
|
||||||
|
lodash: 4.17.21
|
||||||
|
dev: false
|
||||||
|
|
||||||
/d3-array@3.2.2:
|
/d3-array@3.2.2:
|
||||||
resolution: {integrity: sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ==}
|
resolution: {integrity: sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -3474,6 +3504,13 @@ packages:
|
|||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/dagre@0.8.5:
|
||||||
|
resolution: {integrity: sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==}
|
||||||
|
dependencies:
|
||||||
|
graphlib: 2.1.8
|
||||||
|
lodash: 4.17.21
|
||||||
|
dev: false
|
||||||
|
|
||||||
/dashdash@1.14.1:
|
/dashdash@1.14.1:
|
||||||
resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==}
|
resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==}
|
||||||
engines: {node: '>=0.10'}
|
engines: {node: '>=0.10'}
|
||||||
@@ -4465,6 +4502,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==}
|
resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/graphlib@2.1.8:
|
||||||
|
resolution: {integrity: sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==}
|
||||||
|
dependencies:
|
||||||
|
lodash: 4.17.21
|
||||||
|
dev: false
|
||||||
|
|
||||||
/happy-dom@9.18.3:
|
/happy-dom@9.18.3:
|
||||||
resolution: {integrity: sha512-b7iMGYeIXvUryNultA0AHEVU0FPpb2djJ/xSVlMDfP7HG4z7FomdqkCEpWtSv1zDL+t1gRUoBbpqFCoUBvjYtg==}
|
resolution: {integrity: sha512-b7iMGYeIXvUryNultA0AHEVU0FPpb2djJ/xSVlMDfP7HG4z7FomdqkCEpWtSv1zDL+t1gRUoBbpqFCoUBvjYtg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4511,6 +4554,10 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
function-bind: 1.1.1
|
function-bind: 1.1.1
|
||||||
|
|
||||||
|
/heap@0.2.7:
|
||||||
|
resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/htm@3.1.1:
|
/htm@3.1.1:
|
||||||
resolution: {integrity: sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==}
|
resolution: {integrity: sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|||||||
57
src/lib/components/ComfyJourneyView.svelte
Normal file
57
src/lib/components/ComfyJourneyView.svelte
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<!--
|
||||||
|
A "journey" is like browser history for prompts, except organized in a
|
||||||
|
tree-like graph. It lets you save incremental changes to your workflow and
|
||||||
|
jump between past and present sets of parameters.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import Graph from './graph/Graph.svelte'
|
||||||
|
import GraphNode from './graph/GraphNode.svelte'
|
||||||
|
import GraphEdge from './graph/GraphEdge.svelte'
|
||||||
|
|
||||||
|
import type ComfyApp from './ComfyApp';
|
||||||
|
|
||||||
|
export let app: ComfyApp;
|
||||||
|
|
||||||
|
const nodes = [
|
||||||
|
{ id: 'N1', label: 'Start' },
|
||||||
|
{ id: 'N2', label: '4' },
|
||||||
|
{ id: 'N4', label: '8' },
|
||||||
|
{ id: 'N5', label: '15' },
|
||||||
|
{ id: 'N3', label: '16' },
|
||||||
|
{ id: 'N6', label: '23' },
|
||||||
|
{ id: 'N7', label: '42' },
|
||||||
|
{ id: 'N8', label: 'End' }
|
||||||
|
]
|
||||||
|
|
||||||
|
const edges = [
|
||||||
|
{ id: 'E1', source: 'N1', target: 'N2' },
|
||||||
|
{ id: 'E2', source: 'N2', target: 'N3' },
|
||||||
|
{ id: 'E3', source: 'N3', target: 'N6' },
|
||||||
|
{ id: 'E4', source: 'N2', target: 'N4' },
|
||||||
|
{ id: 'E5', source: 'N4', target: 'N5' },
|
||||||
|
{ id: 'E6', source: 'N5', target: 'N4', label: '2' },
|
||||||
|
{ id: 'E7', source: 'N5', target: 'N6' },
|
||||||
|
{ id: 'E8', source: 'N6', target: 'N7' },
|
||||||
|
{ id: 'E9', source: 'N7', target: 'N7', label: '3' },
|
||||||
|
{ id: 'E10', source: 'N7', target: 'N8' }
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="journey-view">
|
||||||
|
<Graph>
|
||||||
|
{#each nodes as node}
|
||||||
|
<GraphNode node={node}/>
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
{#each edges as edge}
|
||||||
|
<GraphEdge edge={edge}/>
|
||||||
|
{/each}
|
||||||
|
</Graph>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.journey-view {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<script context="module" lang="ts">
|
<script context="module" lang="ts">
|
||||||
export type ComfyPaneMode = "none" | "activeWorkflow" | "graph" | "properties" | "templates" | "queue"
|
export type ComfyPaneMode = "none" | "activeWorkflow" | "graph" | "properties" | "templates" | "queue" | "journey"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -8,15 +8,17 @@
|
|||||||
*/
|
*/
|
||||||
import workflowState from "$lib/stores/workflowState";
|
import workflowState from "$lib/stores/workflowState";
|
||||||
import type ComfyApp from "./ComfyApp";
|
import type ComfyApp from "./ComfyApp";
|
||||||
import { Sliders2, BoxSeam, LayoutTextSidebarReverse } from "svelte-bootstrap-icons";
|
import { SvelteComponent } from "svelte";
|
||||||
|
import { capitalize } from "$lib/utils";
|
||||||
|
|
||||||
|
import { Sliders2, BoxSeam, LayoutTextSidebarReverse, Signpost2 } from "svelte-bootstrap-icons";
|
||||||
|
|
||||||
import ComfyBoxWorkflowView from "./ComfyBoxWorkflowView.svelte";
|
import ComfyBoxWorkflowView from "./ComfyBoxWorkflowView.svelte";
|
||||||
import ComfyGraphView from "./ComfyGraphView.svelte";
|
import ComfyGraphView from "./ComfyGraphView.svelte";
|
||||||
import ComfyProperties from "./ComfyProperties.svelte";
|
import ComfyProperties from "./ComfyProperties.svelte";
|
||||||
import ComfyQueue from "./ComfyQueue.svelte";
|
import ComfyQueue from "./ComfyQueue.svelte";
|
||||||
import ComfyTemplates from "./ComfyTemplates.svelte";
|
import ComfyTemplates from "./ComfyTemplates.svelte";
|
||||||
import { SvelteComponent } from "svelte";
|
import ComfyJourneyView from "./ComfyJourneyView.svelte";
|
||||||
import { capitalize } from "$lib/utils";
|
|
||||||
|
|
||||||
export let app: ComfyApp
|
export let app: ComfyApp
|
||||||
export let mode: ComfyPaneMode = "none";
|
export let mode: ComfyPaneMode = "none";
|
||||||
@@ -25,6 +27,7 @@
|
|||||||
const MODES: [ComfyPaneMode, typeof SvelteComponent][] = [
|
const MODES: [ComfyPaneMode, typeof SvelteComponent][] = [
|
||||||
["properties", Sliders2],
|
["properties", Sliders2],
|
||||||
["templates", BoxSeam],
|
["templates", BoxSeam],
|
||||||
|
["journey", Signpost2],
|
||||||
["queue", LayoutTextSidebarReverse]
|
["queue", LayoutTextSidebarReverse]
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -46,8 +49,10 @@
|
|||||||
<ComfyTemplates {app} />
|
<ComfyTemplates {app} />
|
||||||
{:else if mode === "queue"}
|
{:else if mode === "queue"}
|
||||||
<ComfyQueue {app} />
|
<ComfyQueue {app} />
|
||||||
|
{:else if mode === "journey"}
|
||||||
|
<ComfyJourneyView {app} />
|
||||||
{:else}
|
{:else}
|
||||||
<div class="blank-panel">(Blank)</div>
|
<div class="blank-panel">(Blank: {mode})</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if showSwitcher}
|
{#if showSwitcher}
|
||||||
|
|||||||
@@ -7,7 +7,18 @@ import type { ComfyBoxWorkflow } from "./stores/workflowState";
|
|||||||
import { isSerializedPromptInputLink } from "./utils";
|
import { isSerializedPromptInputLink } from "./utils";
|
||||||
import ComfyBoxStdPromptSerializer from "./ComfyBoxStdPromptSerializer";
|
import ComfyBoxStdPromptSerializer from "./ComfyBoxStdPromptSerializer";
|
||||||
|
|
||||||
interface RestoreParamSource {
|
export type RestoreParamType = "workflow" | "backend" | "stdPrompt";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data of a parameter that can be restored. Paired with a parameter name.
|
||||||
|
*/
|
||||||
|
export interface RestoreParamSource<T extends RestoreParamType = any> {
|
||||||
|
type: T,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The actual value to copy to the widget after all conversions have been
|
||||||
|
* applied.
|
||||||
|
*/
|
||||||
finalValue: any
|
finalValue: any
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,7 +27,9 @@ interface RestoreParamSource {
|
|||||||
* *exactly* to a node with the same ID in the current workflow. Easiest case
|
* *exactly* to a node with the same ID in the current workflow. Easiest case
|
||||||
* since the parameter value can just be copied without much fuss.
|
* since the parameter value can just be copied without much fuss.
|
||||||
*/
|
*/
|
||||||
interface RestoreParamSourceWorkflowNode extends RestoreParamSource {
|
export interface RestoreParamSourceWorkflowNode extends RestoreParamSource<"workflow"> {
|
||||||
|
type: "workflow",
|
||||||
|
|
||||||
sourceNode: SerializedComfyWidgetNode
|
sourceNode: SerializedComfyWidgetNode
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +44,9 @@ interface RestoreParamSourceWorkflowNode extends RestoreParamSource {
|
|||||||
* prompt endpoint. Hence this parameter source won't account for those kinds of
|
* prompt endpoint. Hence this parameter source won't account for those kinds of
|
||||||
* values.)
|
* values.)
|
||||||
*/
|
*/
|
||||||
interface RestoreParamSourceBackendNodeInput extends RestoreParamSource {
|
export interface RestoreParamSourceBackendNodeInput extends RestoreParamSource<"backend"> {
|
||||||
|
type: "backend",
|
||||||
|
|
||||||
backendNode: SerializedComfyWidgetNode,
|
backendNode: SerializedComfyWidgetNode,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -45,7 +60,9 @@ interface RestoreParamSourceBackendNodeInput extends RestoreParamSource {
|
|||||||
/*
|
/*
|
||||||
* A value contained in the standard prompt extracted from the saved workflow.
|
* A value contained in the standard prompt extracted from the saved workflow.
|
||||||
*/
|
*/
|
||||||
interface RestoreParamSourceStdPrompt<T, K extends keyof T> extends RestoreParamSource {
|
export interface RestoreParamSourceStdPrompt<T, K extends keyof T> extends RestoreParamSource<"stdPrompt"> {
|
||||||
|
type: "stdPrompt",
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Name of the group containing the value to pass
|
* Name of the group containing the value to pass
|
||||||
*
|
*
|
||||||
@@ -128,35 +145,48 @@ function findUpstreamSerializedWidgetNode(prompt: SerializedPrompt, input: INode
|
|||||||
return [null, null];
|
return [null, null];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function restoreParameters(workflow: ComfyBoxWorkflow, prompt: SerializedPrompt): RestoreParamTargets {
|
const addSource = (result: RestoreParamTargets, targetNode: ComfyWidgetNode, source: RestoreParamSource) => {
|
||||||
const result = {}
|
|
||||||
|
|
||||||
const addSource = (targetNode: ComfyWidgetNode, source: RestoreParamSource) => {
|
|
||||||
result[targetNode.id] ||= { targetNode, sources: [] }
|
result[targetNode.id] ||= { targetNode, sources: [] }
|
||||||
result[targetNode.id].sources.push(source);
|
result[targetNode.id].sources.push(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mergeSources = (a: RestoreParamTargets, b: RestoreParamTargets) => {
|
||||||
|
for (const [k, vs] of Object.entries(b)) {
|
||||||
|
a[vs.targetNode.id] ||= { targetNode: vs.targetNode, sources: [] }
|
||||||
|
for (const source of vs.sources) {
|
||||||
|
a[vs.targetNode.id].sources.push(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getWorkflowRestoreParams(workflow: ComfyBoxWorkflow, prompt: SerializedPrompt): RestoreParamTargets {
|
||||||
|
const result = {}
|
||||||
|
|
||||||
const graph = workflow.graph;
|
const graph = workflow.graph;
|
||||||
|
|
||||||
// Step 1: Find nodes that correspond to *this* workflow exactly, since we
|
|
||||||
// can easily match up the nodes between each (their IDs will be the same)
|
|
||||||
for (const serNode of prompt.workflow.nodes) {
|
for (const serNode of prompt.workflow.nodes) {
|
||||||
const foundNode = graph.getNodeByIdRecursive(serNode.id);
|
const foundNode = graph.getNodeByIdRecursive(serNode.id);
|
||||||
if (isComfyWidgetNode(foundNode) && foundNode.type === serNode.type) {
|
if (isComfyWidgetNode(foundNode) && foundNode.type === serNode.type) {
|
||||||
const finalValue = (serNode as SerializedComfyWidgetNode).comfyValue;
|
const finalValue = (serNode as SerializedComfyWidgetNode).comfyValue;
|
||||||
if (finalValue != null) {
|
if (finalValue != null) {
|
||||||
const source: RestoreParamSourceWorkflowNode = {
|
const source: RestoreParamSourceWorkflowNode = {
|
||||||
|
type: "workflow",
|
||||||
finalValue,
|
finalValue,
|
||||||
sourceNode: serNode
|
sourceNode: serNode
|
||||||
}
|
}
|
||||||
addSource(foundNode, source)
|
addSource(result, foundNode, source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2: Figure out what parameters the backend received. If there was a
|
return result
|
||||||
// widget node attached to a backend node's input upstream, then we can
|
}
|
||||||
// use that value.
|
|
||||||
|
export function getBackendRestoreParams(workflow: ComfyBoxWorkflow, prompt: SerializedPrompt): RestoreParamTargets {
|
||||||
|
const result = {}
|
||||||
|
|
||||||
|
const graph = workflow.graph;
|
||||||
|
|
||||||
for (const [serNodeID, inputs] of Object.entries(prompt.output)) {
|
for (const [serNodeID, inputs] of Object.entries(prompt.output)) {
|
||||||
const serNode = prompt.workflow.nodes.find(sn => sn.id === serNodeID)
|
const serNode = prompt.workflow.nodes.find(sn => sn.id === serNodeID)
|
||||||
if (serNode == null)
|
if (serNode == null)
|
||||||
@@ -176,27 +206,47 @@ export default function restoreParameters(workflow: ComfyBoxWorkflow, prompt: Se
|
|||||||
const foundNode = graph.getNodeByIdRecursive(serNode.id);
|
const foundNode = graph.getNodeByIdRecursive(serNode.id);
|
||||||
if (isComfyWidgetNode(foundNode) && foundNode.type === serNode.type) {
|
if (isComfyWidgetNode(foundNode) && foundNode.type === serNode.type) {
|
||||||
const source: RestoreParamSourceBackendNodeInput = {
|
const source: RestoreParamSourceBackendNodeInput = {
|
||||||
|
type: "backend",
|
||||||
finalValue: inputValue,
|
finalValue: inputValue,
|
||||||
backendNode: serNode,
|
backendNode: serNode,
|
||||||
isDirectAttachment
|
isDirectAttachment
|
||||||
}
|
}
|
||||||
addSource(foundNode, source)
|
addSource(result, foundNode, source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function restoreParameters(workflow: ComfyBoxWorkflow, prompt: SerializedPrompt): RestoreParamTargets {
|
||||||
|
const result = {}
|
||||||
|
|
||||||
|
// Step 1: Find nodes that correspond to *this* workflow exactly, since we
|
||||||
|
// can easily match up the nodes between each (their IDs will be the same)
|
||||||
|
const workflowParams = getWorkflowRestoreParams(workflow, prompt);
|
||||||
|
mergeSources(result, workflowParams);
|
||||||
|
|
||||||
|
// Step 2: Figure out what parameters the backend received. If there was a
|
||||||
|
// widget node attached to a backend node's input upstream, then we can
|
||||||
|
// use that value.
|
||||||
|
const backendParams = getBackendRestoreParams(workflow, prompt);
|
||||||
|
mergeSources(result, backendParams);
|
||||||
|
|
||||||
// Step 3: Extract the standard prompt from the workflow and use that to
|
// Step 3: Extract the standard prompt from the workflow and use that to
|
||||||
// infer parameter types
|
// infer parameter types
|
||||||
|
|
||||||
const serializer = new ComfyBoxStdPromptSerializer();
|
// TODO
|
||||||
const stdPrompt = serializer.serialize(prompt);
|
|
||||||
|
|
||||||
const allWidgetNodes = Array.from(graph.iterateNodesInOrderRecursive()).filter(isComfyWidgetNode);
|
// const serializer = new ComfyBoxStdPromptSerializer();
|
||||||
|
// const stdPrompt = serializer.serialize(prompt);
|
||||||
|
|
||||||
for (const widgetNode of allWidgetNodes) {
|
// const allWidgetNodes = Array.from(graph.iterateNodesInOrderRecursive()).filter(isComfyWidgetNode);
|
||||||
|
|
||||||
}
|
// for (const widgetNode of allWidgetNodes) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
// for (const [groupName, groups] of Object.entries(stdPrompt)) {
|
// for (const [groupName, groups] of Object.entries(stdPrompt)) {
|
||||||
// }
|
// }
|
||||||
|
|||||||
Reference in New Issue
Block a user