Prompt serializer and test fixes
This commit is contained in:
@@ -42,7 +42,7 @@ import type { ComfyBoxStdPrompt } from "$lib/ComfyBoxStdPrompt";
|
||||
import ComfyBoxStdPromptSerializer from "$lib/ComfyBoxStdPromptSerializer";
|
||||
import selectionState from "$lib/stores/selectionState";
|
||||
import layoutStates from "$lib/stores/layoutStates";
|
||||
import { ComfyWorkflow } from "$lib/stores/workflowState";
|
||||
import { ComfyWorkflow, type WorkflowAttributes } from "$lib/stores/workflowState";
|
||||
import workflowState from "$lib/stores/workflowState";
|
||||
|
||||
export const COMFYBOX_SERIAL_VERSION = 1;
|
||||
@@ -80,8 +80,8 @@ export type SerializedAppState = {
|
||||
commitHash?: string,
|
||||
/** Graph state */
|
||||
workflow: SerializedLGraph,
|
||||
/** Workflow name */
|
||||
workflowName: string,
|
||||
/** Workflow attributes */
|
||||
attrs: WorkflowAttributes,
|
||||
/** UI state */
|
||||
layout: SerializedLayoutState,
|
||||
/** Position/offset of the canvas at the time of saving */
|
||||
@@ -165,7 +165,7 @@ export default class ComfyApp {
|
||||
|
||||
async setup(): Promise<void> {
|
||||
if (get(this.alreadySetup)) {
|
||||
console.error("Already setup")
|
||||
console.log("Already setup")
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ export default class ComfyApp {
|
||||
if (layoutState == null)
|
||||
throw new Error("Workflow has no layout!")
|
||||
|
||||
const { graph, layout } = workflow.serialize(layoutState);
|
||||
const { graph, layout, attrs } = workflow.serialize(layoutState);
|
||||
const canvas = this.lCanvas.serialize();
|
||||
|
||||
return {
|
||||
@@ -249,6 +249,7 @@ export default class ComfyApp {
|
||||
version: COMFYBOX_SERIAL_VERSION,
|
||||
commitHash: __GIT_COMMIT_HASH__,
|
||||
workflow: graph,
|
||||
attrs,
|
||||
layout,
|
||||
canvas
|
||||
}
|
||||
@@ -566,7 +567,7 @@ export default class ComfyApp {
|
||||
}
|
||||
}
|
||||
|
||||
if (get(workflow.layout).attrs.queuePromptButtonRunWorkflow) {
|
||||
if (workflow.attrs.queuePromptButtonRunWorkflow) {
|
||||
// Hold control to queue at the front
|
||||
const num = this.ctrlDown ? -1 : 0;
|
||||
this.queuePrompt(num, 1);
|
||||
|
||||
@@ -35,7 +35,15 @@ export function isActiveBackendNode(node: LGraphNode, tag: string | null = null)
|
||||
if (!(node as any).isBackendNode)
|
||||
return false;
|
||||
|
||||
return isActiveNode(node, tag);
|
||||
if (!isActiveNode(node, tag))
|
||||
return false;
|
||||
|
||||
// Make sure this node is not contained in an inactive subgraph, even if the
|
||||
// node itself is active
|
||||
if (node.is(Subgraph) && !Array.from(node.iterateParentNodes()).every(n => isActiveNode(n, tag)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export class UpstreamNodeLocator {
|
||||
@@ -166,7 +174,7 @@ export default class ComfyPromptSerializer {
|
||||
// We don't check tags for non-backend nodes.
|
||||
// Just check for node inactivity (so you can toggle groups of
|
||||
// tagged frontend nodes on/off)
|
||||
if (inputNode && inputNode.mode === NodeMode.NEVER) {
|
||||
if (inputNode && inputNode.mode !== NodeMode.ALWAYS) {
|
||||
console.debug("Skipping inactive node", inputNode)
|
||||
continue;
|
||||
}
|
||||
@@ -248,6 +256,8 @@ export default class ComfyPromptSerializer {
|
||||
const inputs = this.serializeInputValues(node);
|
||||
const links = this.serializeBackendLinks(node, tag);
|
||||
|
||||
console.warn("OUTPUT", node.id, node.comfyClass, node.mode)
|
||||
|
||||
output[String(node.id)] = {
|
||||
inputs: { ...inputs, ...links },
|
||||
class_type: node.comfyClass,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import { LGraphNode } from "@litegraph-ts/core"
|
||||
import { type IDragItem, type WidgetLayout, ALL_ATTRIBUTES, type AttributesSpec, type WritableLayoutStateStore } from "$lib/stores/layoutStates"
|
||||
import uiState from "$lib/stores/uiState"
|
||||
import workflowState from "$lib/stores/workflowState"
|
||||
import layoutStates from "$lib/stores/layoutStates"
|
||||
import selectionState from "$lib/stores/selectionState"
|
||||
import { get, type Writable, writable } from "svelte/store"
|
||||
@@ -127,7 +128,10 @@
|
||||
if (spec.location !== "workflow")
|
||||
return false;
|
||||
|
||||
return spec.name in $layoutState.attrs
|
||||
if (workflow == null)
|
||||
return false;
|
||||
|
||||
return spec.name in workflow.attrs
|
||||
}
|
||||
|
||||
function getAttribute(target: IDragItem, spec: AttributesSpec): any {
|
||||
@@ -240,7 +244,10 @@
|
||||
}
|
||||
|
||||
function getWorkflowAttribute(spec: AttributesSpec): any {
|
||||
let value = $layoutState.attrs[spec.name]
|
||||
if (workflow == null)
|
||||
throw new Error("Active workflow is null!");
|
||||
|
||||
let value = workflow.attrs[spec.name]
|
||||
if (value == null)
|
||||
value = spec.defaultValue
|
||||
else if (spec.serialize)
|
||||
@@ -253,17 +260,20 @@
|
||||
if (!spec.editable)
|
||||
return;
|
||||
|
||||
if (workflow == null)
|
||||
throw new Error("Active workflow is null!");
|
||||
|
||||
const name = spec.name
|
||||
// console.warn("[ComfyProperties] updateWorkflowAttribute", name, value)
|
||||
|
||||
const prevValue = value
|
||||
$layoutState.attrs[name] = value
|
||||
$layoutState = $layoutState
|
||||
workflow.attrs[name] = value
|
||||
$workflowState = $workflowState;
|
||||
|
||||
if (spec.onChanged)
|
||||
spec.onChanged($layoutState, value, prevValue)
|
||||
|
||||
if (spec.refreshPanelOnChange)
|
||||
// if (spec.refreshPanelOnChange)
|
||||
doRefreshPanel()
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
import { tick } from "svelte";
|
||||
import Modal from "./Modal.svelte";
|
||||
import DropZone from "./DropZone.svelte";
|
||||
import workflowState from "$lib/stores/workflowState";
|
||||
|
||||
export let app: ComfyApp;
|
||||
|
||||
@@ -71,10 +72,17 @@
|
||||
const subgraphs: string[] | null = entry.extraData?.extra_pnginfo?.comfyBoxSubgraphs;
|
||||
|
||||
let message = "Prompt";
|
||||
if (subgraphs?.length > 0)
|
||||
message = `Prompt: ${subgraphs.join(', ')}`
|
||||
if (entry.workflowID != null) {
|
||||
const workflow = workflowState.getWorkflow(entry.workflowID);
|
||||
if (workflow != null && workflow.attrs.title) {
|
||||
message = `Workflow: ${workflow.attrs.title}`
|
||||
}
|
||||
if (subgraphs?.length > 0)
|
||||
message += ` (${subgraphs.join(', ')})`
|
||||
}
|
||||
|
||||
let submessage = `Nodes: ${Object.keys(entry.prompt).length}`
|
||||
|
||||
if (Object.keys(entry.outputs).length > 0) {
|
||||
const imageCount = Object.values(entry.outputs).flatMap(o => o.images).length
|
||||
submessage = `Images: ${imageCount}`
|
||||
@@ -84,7 +92,7 @@
|
||||
entry,
|
||||
message,
|
||||
submessage,
|
||||
dateStr,
|
||||
date: dateStr,
|
||||
status: "pending",
|
||||
images: []
|
||||
}
|
||||
@@ -387,7 +395,7 @@
|
||||
|
||||
&.all_cached, &.interrupted {
|
||||
filter: brightness(80%);
|
||||
color: var(--neutral-300);
|
||||
color: var(--comfy-accent-soft);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import { get, writable, type Writable } from "svelte/store";
|
||||
import ComfyProperties from "./ComfyProperties.svelte";
|
||||
import uiState from "$lib/stores/uiState";
|
||||
import workflowState from "$lib/stores/workflowState";
|
||||
import workflowState, { ComfyWorkflow } from "$lib/stores/workflowState";
|
||||
import selectionState from "$lib/stores/selectionState";
|
||||
import type ComfyApp from './ComfyApp';
|
||||
import { onMount } from "svelte";
|
||||
@@ -19,7 +19,7 @@
|
||||
export let app: ComfyApp;
|
||||
export let uiTheme: string = "gradio-dark" // TODO config
|
||||
|
||||
let layoutState: WritableLayoutStateStore | null = null;
|
||||
let workflow: ComfyWorkflow | null = null;
|
||||
|
||||
let containerElem: HTMLDivElement;
|
||||
let resizeTimeout: NodeJS.Timeout | null;
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
let appSetupPromise: Promise<void> = null;
|
||||
|
||||
$: layoutState = $workflowState.activeWorkflow?.layout;
|
||||
$: workflow = $workflowState.activeWorkflow;
|
||||
|
||||
onMount(async () => {
|
||||
appSetupPromise = app.setup().then(() => {
|
||||
@@ -189,10 +189,10 @@
|
||||
<button class="workflow-tab"
|
||||
class:selected={index === $workflowState.activeWorkflowIdx}
|
||||
on:click={() => app.setActiveWorkflow(index)}>
|
||||
<span class="workflow-tab-title">{workflow.title}</span>
|
||||
<span class="workflow-tab-title">{workflow.attrs.title}</span>
|
||||
<button class="workflow-close-button"
|
||||
on:click={(e) => closeWorkflow(e, index)}>
|
||||
X
|
||||
✕
|
||||
</button>
|
||||
</button>
|
||||
{/each}
|
||||
@@ -200,9 +200,9 @@
|
||||
<div id="bottombar">
|
||||
<div class="bottombar-content">
|
||||
<div class="left">
|
||||
{#if layoutState != null && $layoutState.attrs.queuePromptButtonName != ""}
|
||||
{#if workflow != null && workflow.attrs.queuePromptButtonName != ""}
|
||||
<Button variant="primary" disabled={!$alreadySetup} on:click={queuePrompt}>
|
||||
{$layoutState.attrs.queuePromptButtonName}
|
||||
{workflow.attrs.queuePromptButtonName}
|
||||
</Button>
|
||||
{/if}
|
||||
<Button variant="secondary" disabled={!$alreadySetup} on:click={toggleGraph}>
|
||||
@@ -395,11 +395,12 @@
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
border-radius: 50%;
|
||||
opacity: 50%;
|
||||
background: var(--neutral-500);
|
||||
color: var(--neutral-300);
|
||||
|
||||
&:hover {
|
||||
background: var(--neutral-400);
|
||||
opacity: 100%;
|
||||
color: var(--neutral-100);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user